/* The shop: brand A ("HQ, outside"). A web shop first: products, prices and ways in on the first screen; pixels for
   signs and pictures, Atkinson Hyperlegible for every sentence. Phone first (the board's iPhone Air, 420 px), then
   tablet (800) and laptop (1408 x 650). Each stall keeps its own look in its own app, under the shop bar (bar.js). The room between blocks and around sections comes from our theme's one scale
   (spacing.css, a copy of theme/web/spacing.css that demo/shop-check.mjs keeps in step, linked before this file). */

/* Atkinson Hyperlegible (Braille Institute of America), SIL OFL 1.1: fonts/OFL.txt */
@font-face{font-family:'Atkinson Hyperlegible';src:url('/fonts/atkinson-hyperlegible-latin-400-normal.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'Atkinson Hyperlegible';src:url('/fonts/atkinson-hyperlegible-latin-400-italic.woff2') format('woff2');font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:'Atkinson Hyperlegible';src:url('/fonts/atkinson-hyperlegible-latin-700-normal.woff2') format('woff2');font-weight:700;font-display:swap}

:root{--paper:#fffaf0;--paper2:#f7efdf;--night:#2a2352;--ink:#1d1a2f;--muted:#5a5478;--lamp:#ffd966;--brass:#8a5a14;
  --amber:#e8a33d;--gold-lt:#fff3b0;--line:#e8dcc4;--sky:#cfe8fb;--sky2:#eaf5fd;
  --sale:#a3402a;--save:#2f7a3b; /* the brand's brick, darkened for text: 6.3:1 on white, 5.9:1 on paper */
  --sans:'Atkinson Hyperlegible','DejaVu Sans',system-ui,sans-serif}
:where(main > section){padding-block:var(--section)}
*{box-sizing:border-box}
html{background:var(--paper);-webkit-text-size-adjust:100%}
body{margin:0;color:var(--night);font:400 17px/1.6 var(--sans);overflow-x:hidden;}
[hidden]{display:none!important}
img,svg,video,canvas{display:block}
.px,.px img,.sign,.plate,.parcel,.pxlabel{image-rendering:pixelated;image-rendering:crisp-edges}
a{color:var(--brass);text-underline-offset:3px}
/* one focus ring, in the night on the paper (13:1) and the lamp on the night (10:1): WCAG asks 3:1 against its ground.
   Each night ground sets --focus. */
:root{--focus:var(--night)}
:focus-visible{outline:3px solid var(--focus);outline-offset:3px;border-radius:4px}
.strip,.foot,.rule-in,.promo-black-friday,.promo-december,.zoombox{--focus:var(--lamp)}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.wrap{max-width:var(--page);margin:0 auto;padding:0 var(--gutter)}
/* one set of edges: the page is one column, --page wide with the theme's --gutter inside it, and
   what runs the screen's whole width (the strip, the header, the ways in) keeps its words on that column's edges */
:root{--page:1440px;--edge:max(var(--gutter),calc((100% - var(--page)) / 2 + var(--gutter)))}
.wrap.narrow{max-width:720px}
h1{font-size:32px;line-height:1.12;letter-spacing:-.01em;margin:0 0 12px;text-wrap:balance}
h2{font-size:26px;line-height:1.18;margin:0 0 10px;text-wrap:balance}
p,li{text-wrap:pretty}
h2.sub{font-size:22px;margin:var(--space-xl) 0 var(--space-s)}
.intro{font-size:18px;color:var(--muted);margin:0 0 18px;max-width:640px}
.lede{font-size:17px;color:var(--muted);margin:0 0 22px;max-width:640px}
.fine{font-size:15px;color:var(--muted);line-height:1.5}
/* the 5 x 7 labels on whole device pixels so they stay sharp: 5 to a letter's pixel on a 3x screen (5/3 px, a sixth
   smaller than at 2 px), 3 on a 2x one (1.5 px, a quarter smaller); a 1x screen keeps 2, since 1 2/3 can't be drawn
   there without uneven pixels */
:root{--lp:2px}
@media (min-resolution:2dppx){:root{--lp:1.5px}}
@media (min-resolution:3dppx){:root{--lp:calc(5px / 3)}}
.pxlabel{width:auto;height:calc(7 * var(--lp))}
.label{display:flex;align-items:center;gap:12px;color:var(--brass);margin:0 0 var(--space-s);min-height:calc(7 * var(--lp))}
.label::before{content:'';flex:none;width:9px;height:9px;background:var(--amber);box-shadow:0 0 0 3px var(--gold-lt)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;font:700 17px/1.1 var(--sans);padding:14px 22px;min-height:48px;border-radius:99px;text-decoration:none;border:0;cursor:pointer}
/* every button is the chat's pill: the night one darkens on hover, the paper one's ring does */
.btn.main{background:var(--night);color:var(--paper)}
.btn.main:hover{background:var(--ink)}
.btn.quiet{color:var(--night);background:var(--paper);box-shadow:inset 0 0 0 2px var(--line)}
.btn.quiet:hover{box-shadow:inset 0 0 0 2px var(--night)}
.btn.wide{display:flex;width:100%}
.btn:disabled{opacity:.75;cursor:progress}
.btns{display:flex;gap:12px;flex-wrap:wrap}
.band{background:var(--paper2)}
main{display:block;min-height:60vh}
main:focus{outline:none}
/* the top of a page, one rhythm on every page: the breadcrumbs one --space-l
   above what follows them, a label or the heading, and a label (.label's own margin) one --space-s above its heading */
.crumbs{font-size:15px;color:var(--muted);margin:16px 0 var(--space-l)}
.crumbs a{color:var(--muted)}
.chip{display:inline-flex;align-items:center;gap:7px;align-self:flex-start;font-size:14px;font-weight:700;line-height:1.25;color:var(--night);background:var(--paper);border-radius:99px;padding:5px 11px 5px 9px}
.chip::before{content:'';flex:none;width:8px;height:8px;background:var(--amber)}
input,select{font:400 17px/1.3 var(--sans);color:var(--night);background:#fff;border:2px solid var(--line);border-radius:10px;padding:11px 12px;min-height:48px;width:100%}
input:focus,select:focus{outline:none;border-color:var(--night)}
/* Safari draws its own select at its own height, whatever the padding says: our own box and chevron, as tall as an input */
select{-webkit-appearance:none;appearance:none;padding-right:40px;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%232a2352' stroke-width='2'/%3E%3C/svg%3E") no-repeat right 15px center/12px 8px}

/* ---------------------------------------------------------------- the header: logo, search, ways in, basket */
/* The strip's promises show while they fit on its one line (the board's notes #51, #70), whatever the language: each
   group is a wrapping row one line high, so a promise with no room left wraps out of sight. An empty first item holds
   the first line, so even the first promise can wrap away. Delivery included stays (its short words under it show
   once the whole sentence doesn't fit), and the rest share what's left: made to order goes first, then the saving,
   which is placed first but drawn last (row-reverse). */
.usp{display:flex;margin:0;padding:3px 0;min-width:0;color:var(--paper);font-size:14px;line-height:21px;white-space:nowrap;overflow:hidden}
.usp-first,.usp-more{display:flex;flex-wrap:wrap;height:21px;overflow:hidden}
.usp-first::before,.usp-more::before{content:'';order:-2;height:21px}
.usp-first{position:relative;flex:0 1 auto;min-width:0}
.usp-first>span:first-child{position:relative;z-index:1;background:var(--night)}
.usp-short{position:absolute;left:0;top:0}
.usp-more{flex:1 1 0;min-width:0;flex-direction:row-reverse;justify-content:flex-end}
.usp-more>span{margin-left:18px}
.usp-saving{order:-1}
.usp-first>span::before,.usp-more>span::before{content:'';display:inline-block;width:7px;height:7px;margin-right:8px;background:var(--lamp);vertical-align:1px}
/* On a phone the three promises take turns in one place: stacked in one cell, so the strip is as
   tall as its longest line (one line from 390 px, two on a narrower phone in Dutch or German) and never
   changes height as they turn. shop.js turns them every few seconds (.on), the old one fading out before the new one fades
   in; without JS the first one stays. Every promise is still in the text for a screen reader, read once, in order. The
   pause button beside them (shop.js) shows only here, where they turn, its hit area the 24 px WCAG asks for. */
@media (max-width:699px){
  .usp{display:grid;flex:1 1 auto;white-space:normal}
  .usp-first,.usp-more{display:contents}
  .usp-first::before,.usp-more::before,.usp-short{display:none}
  :is(.usp-first>span:first-child,.usp-more>span){grid-area:1/1;margin:0;opacity:0;text-wrap:balance;transition:opacity .35s ease-in}
  :is(.usp-first>span:first-child,.usp-more>span).on,.usp:not(.turning) .usp-first>span:first-child{opacity:1;transition-delay:.35s;transition-timing-function:ease-out}
}
/* the longest promise (Dutch's made to order) needs 256 px at 14 px: a point smaller keeps it on one line from 390 px */
@media (max-width:419px){.usp{font-size:13px}}
.top{position:sticky;top:0;z-index:50;background:var(--paper);box-shadow:0 2px 0 var(--line)}
/* the shop's awning: the stalls' striped canopy (pixels.js sign()) hung under the header, at a whole 2x, over the page
   rather than in it, so nothing under it moves; its pale stripes are shaded and hemmed, so it reads as one cloth on the
   paper rather than a row of amber bulbs (the board's note #26), and the ways in start below it with room to breathe */
body .top{box-shadow:none}
body .top::after{content:'';position:absolute;left:0;right:0;top:100%;height:16px;pointer-events:none;
  background:var(--top-awning,url(/shop/img/awning.svg)) 0 0/24px 16px repeat-x;image-rendering:pixelated}
.bar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:0 10px 0 var(--edge);background:var(--paper)}
.logo{display:flex;align-items:center;min-height:56px}
.logo img{width:198px;height:32px}
.nav{display:flex;align-items:center;gap:0}
.nav>a:not(.basket-btn):not(.chat-btn){display:inline-flex;align-items:center;min-height:44px;padding:0 9px;color:var(--night);text-decoration:none;font-size:15px;font-weight:700}
.nav>a[aria-current]:not(.basket-btn):not(.chat-btn){text-decoration:underline;text-decoration-color:var(--amber);text-decoration-thickness:3px;text-underline-offset:6px}
.basket-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;min-width:52px;min-height:44px;text-decoration:none}
.basket-btn .bicon svg,.receipt .bicon svg{width:26px;height:20px}
.count{position:absolute;top:2px;right:2px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;background:var(--night);color:var(--paper);font:700 14px/20px var(--sans);text-align:center}
.count[data-n="0"]{background:var(--line);color:var(--muted)}
.search{flex:1 1 100%;position:relative;display:flex;margin:0 10px 13px 0;border:2px solid var(--night);border-radius:12px;background:#fff}
/* the suggestions as you type (suggest.js), hung under the field over the page */
.suggest{position:absolute;max-height:calc(100dvh - 150px);overflow-y:auto;z-index:30;left:-2px;right:-2px;top:calc(100% + 6px);margin:0;padding:6px;list-style:none;border:2px solid var(--night);border-radius:12px;background:#fff;box-shadow:0 10px 24px rgba(29,36,64,.18)}
.suggest a{display:flex;align-items:center;gap:12px;min-height:44px;padding:4px 8px;border-radius:8px;color:var(--night);text-decoration:none}
.suggest img{flex:none;width:64px;height:48px;border-radius:6px;object-fit:cover}
.suggest .sname{flex:1;font-weight:700}
.suggest .sstall{color:var(--muted);font-size:14px}
.suggest .sall{font-weight:700;text-decoration:underline;text-decoration-color:var(--amber);text-decoration-thickness:2px;text-underline-offset:4px}
.suggest [aria-selected=true] a,.suggest a:hover{background:var(--gold-lt)}
.suggest .snone{padding:10px 8px;color:var(--muted)}
.search input{border:0;border-radius:0;min-height:42px;padding:8px 12px;font-size:16px;background:none}
.search input:focus{outline:none}
.search:focus-within{outline:3px solid var(--focus);outline-offset:2px}
/* Where the search wraps, only the logo's row stays on screen as the page scrolls (the board's note #78), the awning
   comes up to hang under it and the search slides away under both. Each is one layer, never a sticky inside a sticky,
   which iOS WebKit loses as it scrolls: the header's wrapper draws no box, the
   logo's row sticks at the top, the search's row scrolls with the page, and the awning sticks under the row without
   taking room. A search with the focus sticks under the row, the awning under it (56 + its 46 + 13). Nothing in the
   page moves. */
@media (max-width:1099px){
  .top{display:contents;position:static}
  .shopbar{position:sticky;top:0;z-index:50}
  body .top::after{position:sticky;display:block;inset:56px auto auto;z-index:50;margin-bottom:-16px}
  .top:has(.search:focus-within)::after{top:115px}
  .searchbar:focus-within{position:sticky;top:56px;z-index:51}
}
.search button{flex:none;width:52px;border:0;border-radius:0 10px 10px 0;background:var(--night);color:var(--paper);display:grid;place-items:center;cursor:pointer}
.ways{display:flex;gap:8px;overflow-x:auto;padding:28px var(--edge) 14px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.ways::-webkit-scrollbar{display:none}
.ways a{flex:none;display:inline-flex;align-items:center;min-height:38px;padding:0 14px;border-radius:99px;background:#fff;box-shadow:inset 0 0 0 1.5px var(--line);color:var(--night);text-decoration:none;font-size:15px;font-weight:700;white-space:nowrap}
.ways a.hot{background:var(--sale);color:#fff;box-shadow:none}
/* a way in lights up under the pointer, and the page you're on has a dark border */
.ways a:hover{background:var(--gold-lt);box-shadow:inset 0 0 0 1.5px var(--amber)}
.ways a.hot:hover{background:#8a3322;box-shadow:none}
.ways a[aria-current]{background:#fff;color:var(--night);box-shadow:inset 0 0 0 2px var(--night)}
.ways a[aria-current]:hover{background:var(--gold-lt);color:var(--night)}
/* on a phone its short words, so more ways fit on the screen; a screen reader hears the whole name */
.way-short{display:none}
@media (max-width:699px){
  .ways a{position:relative}
  .ways .way-long{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .ways .way-short{display:inline}
}
.back{display:inline-flex;align-items:center;gap:8px;min-height:44px;color:var(--night);text-decoration:none;font-size:15px;line-height:1.2}

/* ---------------------------------------------------------------- products: cards with picture, name and price */
.grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-l) var(--space-s)}
.pcard,.scard{display:flex;flex-direction:column;color:var(--night);text-decoration:none;min-width:0}
.pimg{position:relative;display:block;aspect-ratio:1;border-radius:14px;overflow:hidden;background:var(--tint,#fff)}
.pimg img{width:100%;height:100%;object-fit:cover}
.pcard:hover .pimg img{transform:scale(1.03);transition:transform .4s}
/* each card is the thing made for three people in turn, under its stall's awning: 6 s each, the cards a beat apart
   (--turn), still with reduced motion. The picture crossfades in 0.6 s */
.pcard .pimg::before{content:"";position:absolute;inset:0 0 auto;z-index:2;height:16px;
  background:var(--awning) 50% 0/12px 16px repeat-x;image-rendering:pixelated;image-rendering:crisp-edges}
.pcard .badge{top:22px;z-index:3}
:is(.pimg,.thing-pic) .ver{position:absolute;inset:0;z-index:1;opacity:0;animation:18s linear var(--turn,0s) infinite both}
:is(.pimg,.thing-pic) .ver2{animation-name:ver2}:is(.pimg,.thing-pic) .ver3{animation-name:ver3}
@keyframes ver2{0%,30%{opacity:0}33.333%,66.667%{opacity:1}66.7%,100%{opacity:0}}
@keyframes ver3{0%,63.333%{opacity:0}66.667%,96.667%{opacity:1}100%{opacity:0}}
@keyframes ring1{0%,30%{opacity:1}31.667%,98.333%{opacity:0}100%{opacity:1}}
@keyframes ring2{0%,31.667%{opacity:0}33.333%,63.333%{opacity:1}65%,100%{opacity:0}}
@keyframes ring3{0%,65%{opacity:0}66.667%,96.667%{opacity:1}98.333%,100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.pimg .ver{display:none}}
.badge{position:absolute;left:8px;top:8px;padding:3px 8px;border-radius:8px;background:var(--sale);color:#fff;font-size:15px;font-weight:700;line-height:1.3}
.pbody{flex:1;display:flex;flex-direction:column;gap:1px;padding:8px 2px 0}
/* what makes a card orderable (the board's note #32): its price with delivery, and "Make yours", at the card's foot so
   every card in a row ends on one line */
.pbuy{margin-top:auto;padding-top:var(--space-xs);display:flex;flex-direction:column;gap:var(--space-s)}
.pbuy .price{line-height:1.3}
.price .dlv{font-size:15px;font-weight:400;color:var(--muted)}
.pgo{display:flex;align-items:center;justify-content:center;gap:6px;min-height:44px;padding:0 8px;border-radius:99px;font-size:15px;font-weight:700;
  line-height:1.2;white-space:nowrap;color:var(--night);background:var(--paper);box-shadow:inset 0 0 0 2px var(--night)}
@media (max-width:359px){.pgo{font-size:14px;gap:4px}}
.pcard:hover .pgo,.pcard:focus-visible .pgo{background:var(--night);color:var(--paper)}
.pshop{font-size:14px;font-weight:700;color:var(--muted);display:flex;align-items:center;gap:6px}
.pshop::before{content:'';width:8px;height:8px;background:var(--acc);flex:none}
/* a stall with an emblem wears it instead of the square (the board's note #61) */
.pshop:has(.emblem)::before{display:none}
.pshop .emblem{flex:none}
.stall-mark{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.pshop:has(.stall-mark)::before{display:none}
.stall-mark:not(:has(.emblem))::before{content:'';width:8px;height:8px;background:var(--acc);flex:none}
.pname{font-size:17px;font-weight:700;line-height:1.25}
/* the line on whom it's for, whole: the cards' prices and buttons still end level along a row (.pbuy) */
.pshort{font-size:15px;line-height:1.35;color:var(--muted)}
/* on a gift page, why it suits the moment, in the tagline's place: in the ink, so it reads as the card's answer to the
   page's question */
.pwhy{font-size:15px;line-height:1.35}
.price{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;margin:4px 0 0;font-size:18px}
.price .now{font-weight:700}
.price.sale .now{color:var(--sale)}
.price .was{font-size:15px;color:var(--muted)}
.offer-note{display:block;margin:0;font-size:14px;color:var(--muted);line-height:1.35}
.scard .pimg{aspect-ratio:4/3}
.scard .chip{margin-top:6px;background:var(--paper2)}
/* our next ideas: a peek through the workshop's frosted window (the picture comes blurred, tools/peeks.mjs), two glints on the glass */
.peek::after{content:"";position:absolute;inset:0;background:linear-gradient(115deg,rgba(255,255,255,.38) 0 16%,transparent 16% 27%,rgba(255,255,255,.2) 27% 33%,transparent 33%)}
.soon-grid{align-items:start}
.hear{margin-top:6px}
.hear summary{cursor:pointer;list-style:none;background:#fff;box-shadow:inset 0 0 0 2px var(--line)}
.hear summary::-webkit-details-marker{display:none}
.hear summary:hover,.hear[open] summary{box-shadow:inset 0 0 0 2px var(--night)}
.hear-do{margin-top:var(--space-s)}
.hear .letter-row{flex-direction:column}
.hear .letter-small{font-size:14px;line-height:1.45}
.hear .letter-thanks{padding:var(--space-s) var(--space-m);font-size:15px;line-height:1.45}
/* "All gifts" sits on the heading's last line where it wraps, as on a phone */
.head-row{display:flex;align-items:baseline;align-items:last baseline;justify-content:space-between;gap:12px;margin:0 0 var(--head-gap)}
.head-row h1{font-size:22px;margin:0}
.head-row a{font-weight:700;font-size:15px;white-space:nowrap}
.count-line{font-size:15px;color:var(--muted);margin:0 0 10px}
.empty-line{color:var(--muted)}

/* ---------------------------------------------------------------- the front page */
.promo{background:var(--paper2);border-bottom:1px solid var(--line);padding-block:0} /* a thin banner: its room is inside (.promo-in) */
.promo-in{padding-top:var(--space-m);padding-bottom:var(--space-m)}
.promo h2{font-size:22px;line-height:1.2;margin:0 0 4px}
.promo p:not(.label){margin:0;font-size:16px;line-height:1.45;color:var(--muted)}
.promo p a{font-weight:700;white-space:nowrap}
/* a title naming a few things: each word leads to its thing */
.promo h2 a{color:inherit;text-decoration-color:var(--amber);text-decoration-thickness:3px;text-underline-offset:4px}
.promo h2 a:hover{color:var(--brass)}
.promo-black-friday{background:var(--ink);border-color:var(--ink)}
.promo-black-friday .label{color:var(--lamp)}
.promo-black-friday h2{color:#fff}
.promo-black-friday p{color:#d9d3ea}
.promo-black-friday p a{color:var(--lamp)}
.promo-december{background:#203a33;border-color:#203a33}
.promo-december .label{color:var(--lamp)}
.promo-december .label::before{background:#d9573b;box-shadow:0 0 0 3px #f2c9bd}
.promo-december h2{color:#fff}
.promo-december p{color:#d6e6df}
.promo-december p a{color:var(--lamp)}
/* the gifts' heading sits as far below the news band as above its cards */
.shelf{padding-block:var(--head-gap) var(--space-2xl)}
.shelf .fine{margin:var(--space-l) 0 0}
/* the shop's rule, €4 off every extra thing (the board, call #84): a night card with an example receipt, its saving
   stamped on each extra thing (shop.js adds .play once it's in view; without JS or with reduced motion it's just there) */
/* the products, the €4 card and the next band one step apart: no empty stretch above the card */
.rule{padding-block:0 var(--space-2xl)}
.rule-in{display:grid;gap:var(--space-xl);align-items:center;background:var(--night);color:var(--paper);border-radius:20px;padding:var(--space-xl) var(--space-l) var(--space-2xl);box-shadow:0 4px 0 var(--ink)}
.rule .label{color:var(--lamp)}
.rule h2{color:#fff;font-size:30px;margin-bottom:12px}
.rule h2 em{font-style:normal;color:var(--lamp)}
.rule-say p:not(.label){margin:0 0 var(--space-m);color:#ddd8ee;max-width:560px}
.rule-say .rule-more{margin:0}
.rule-more a{color:var(--lamp);font-weight:700}
.receipt{justify-self:center;width:min(100%,340px);margin:0;padding:16px 18px 30px;background:var(--paper);color:var(--ink);transform:rotate(1.2deg);font-variant-numeric:tabular-nums;
  -webkit-mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/14px 100%;mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/14px 100%}
.receipt figcaption{display:flex;align-items:center;gap:10px;font-size:14px;font-weight:700;color:var(--muted);padding-bottom:8px;border-bottom:2px dashed var(--line)}
.receipt .bicon{display:flex}
.receipt ul{list-style:none;margin:0;padding:0}
.receipt li{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:10px;align-items:start;padding:10px 0;border-bottom:1px dashed var(--line);font-size:16px;line-height:1.3}
.receipt .what{grid-row:span 2}
.receipt .what small{display:block;font-size:13px;color:var(--muted)}
.receipt .rprice{font-weight:700}
.stamp{grid-column:2;justify-self:end;margin-top:4px;padding:1px 8px;border:2px solid var(--save);border-radius:6px;color:var(--save);background:#eaf5e4;font-weight:700;font-size:17px;transform:rotate(-8deg)}
.rule.play .stamp{animation:stamp .32s cubic-bezier(.3,1.5,.5,1) backwards}
.rule.play li:nth-child(2) .stamp{animation-delay:.35s}
.rule.play li:nth-child(3) .stamp{animation-delay:.8s}
@keyframes stamp{from{opacity:0;transform:rotate(-8deg) scale(2.4)}}
/* what the stamps save, summed at the slip's foot, in the stamps' green: it lands after the last stamp */
.rsaved{margin:10px 0 0;text-align:end;color:var(--save);font-weight:700;font-size:16px}
.rule.play .rsaved{animation:saved .4s ease-out 1.2s backwards}
@keyframes saved{from{opacity:0;transform:translateY(-4px)}}
/* a phone: the card takes more of the width, so the 3x pixel label fits in every language (20 letters at 320 px) */
@media (max-width:419px){.rule .wrap{padding:0 8px}.rule-in{padding-inline:20px}}
@media (min-width:700px){.rule-in{padding:var(--space-2xl)}.rule h2{font-size:34px}}
/* the words and the receipt fill the card, centred on each other top to bottom, with the same room on every side of the
   card: the words take the width the receipt leaves, so nothing piles up between the two */
@media (min-width:900px){.rule-in{grid-template-columns:minmax(0,1fr) 360px;gap:var(--space-3xl);padding:var(--space-2xl)}.rule-say p{max-width:none}}
/* beside the words the receipt is a till slip, one line a thing (its stall after its name, its stamp before its price),
   so it's no taller than the words and the card is only as tall as they need */
@media (min-width:900px){
  .receipt{width:360px;padding:12px 18px 24px}
  .receipt figcaption{padding-bottom:4px}
  .receipt ul{display:grid;grid-template-columns:minmax(0,1fr) auto auto;column-gap:10px}
  .receipt li{grid-column:1/-1;grid-template-columns:subgrid;align-items:center;padding:8px 0}
  .receipt .what{grid-row:auto}
  .receipt .what small{display:inline;margin-left:6px}
  .receipt .rprice{grid-column:3;grid-row:1}
  .stamp{grid-column:2;grid-row:1;margin:0;font-size:15px}
}
section.band,.stalls-sec,.soon,.letter{padding-block:var(--section)}
/* one rhythm (the board's notes #29 and #32): every section has the theme's --section above and below, and its
   heading (label, title, lede) sits the same --head-gap above what it introduces */
:root{--head-gap:var(--space-l)}
@media (min-width:700px){:root{--head-gap:var(--space-xl)}}
.stalls,.soon-grid{margin-top:var(--head-gap)}
main section .lede{margin-bottom:0}
/* the signs fill their row, as many to a row as fit, each from its column's left edge as the heading above them: on a
   phone two to a row, so every name fits on one line and the counts line up; from 600 px every column at least as wide
   as the longest name.
   A 320 px phone sets the names a size smaller to keep them on one line */
.signs{list-style:none;margin:var(--head-gap) 0 0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-xs) var(--space-s)}
@media (min-width:600px){.signs{grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}}
/* from 900 px all five in five equal columns, each sign at the start of its own (spread from edge to edge they left
   wide gaps), and from a laptop up (1100 px, below) half again as large: signs drawn with more pixels (72 x 60, the
   picture's source in views.js), still at 2 a pixel */
@media (min-width:900px){.signs{grid-template-columns:repeat(5,minmax(0,1fr))}}
.signs a{display:flex;flex-direction:column;align-items:flex-start;text-align:start;color:var(--night);text-decoration:none;padding:0 2px}
.signs a:hover .hang,.signs a:focus-visible .hang{animation:sway 1.2s ease-in-out}
@keyframes sway{25%{transform:rotate(3deg)}60%{transform:rotate(-2deg)}85%{transform:rotate(.6deg)}}
.hang{width:96px;height:80px;transform-origin:50% 0}
.hang img{width:96px;height:80px}
@media (min-width:1100px){.hang,.hang img{width:144px;height:120px}}
.signs b{font-size:16px;line-height:1.25;margin-top:6px}
@media (max-width:339px){.signs b{font-size:14px}}
.signs span{font-size:14px;color:var(--muted)}
/* the stalls: white cards at least 280 px wide, as many to a row as fit (four on the board's laptop); on a phone one,
   at most 360 px, centred */
.stalls{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--space-2xl) var(--space-l)}
@media (max-width:647px){.stalls{grid-template-columns:minmax(0,360px);justify-content:center}}
/* the stall drawn in the middle of its colour at the top, at 2 CSS pixels a pixel (img/stalls/<key>.png: at rest, then
   four frames lit and stirring), and the thing at home over it covering the same spot: 4:5, the card's whole width;
   the words 24 px in */
.stall{--band:calc(100cqw * 1.25);--pad:24px;
  position:relative;display:flex;flex-direction:column;min-width:0;container-type:inline-size;background:#fff;color:var(--night);
  border-radius:12px;overflow:hidden;box-shadow:0 1px 2px rgb(42 35 82 / .08),0 8px 24px rgb(42 35 82 / .10);transition:box-shadow .2s}
.stall:has(a.go):hover{box-shadow:0 1px 2px rgb(42 35 82 / .10),0 12px 32px rgb(42 35 82 / .16)}
.stall:has(.go:focus-visible){outline:3px solid var(--night);outline-offset:4px}
.spot{position:relative;display:block;height:var(--band);background:var(--wash)}
.drawn{display:block;width:220px;height:292px;margin:round(down,(var(--band) - 292px) / 2,1px) auto 0;background:var(--drawn) 0 0/1100px 292px;
  image-rendering:pixelated;image-rendering:crisp-edges;transition:transform .25s steps(2)}
/* pointed at, the stall lights its bulbs and lifts a pixel, and its wares stir */
.stall:is(:has(a.go):hover,:has(.go:focus-visible),.stirred) .drawn{background-position-x:-220px;transform:translateY(-2px)}
@keyframes stir{from{background-position-x:-220px}to{background-position-x:-1100px}}
.home{position:absolute;inset:0;opacity:0}
.home img{display:block;width:100%;height:100%}
/* "Mockup, not a photo" on the picture's bottom-left corner, showing with the picture */
.stall .mock{position:absolute;left:0;bottom:0;padding:5px 10px;border-radius:0 8px 0 0;background:rgb(29 26 47 / .78);color:#fff;
  font-size:14px;font-weight:700;line-height:18px;white-space:nowrap}
/* the words the card's width: the stall's name, its line, the price 8 px under it, the way in 14 px under the price; the
   link covers the card. Snug enough that a card with a four-line line still fits the board's 611 px tall laptop window
   whole */
.go{display:flex;flex-direction:column;align-items:flex-start;flex:1;padding:16px var(--pad) 20px;color:var(--night);text-decoration:none}
/* a swipe across a stall that turns is its own, never the page's (stalls.js) */
.stall[data-turns]{touch-action:pan-y}
a.go::after{content:'';position:absolute;inset:0}
.go:focus-visible{outline:none}
/* the stall's name with its mark heads the words, as on its name board, at 3 CSS pixels a pixel */
.stall .stall-mark{gap:8px;margin-bottom:4px;font-size:19px;line-height:24px}
.stall .stall-mark .emblem{width:21px;height:21px}
.stall .stall-mark:not(:has(.emblem))::before{width:12px;height:12px}
.stall .sline{color:var(--night);font-size:16px;line-height:1.5;text-wrap:pretty}
.stall .from{margin-top:8px;font-size:16px;font-weight:700;line-height:1.4}
.stall .btn,.stall .chip{margin-top:14px}
.stall:has(a.go):hover .btn{background:var(--ink)}
/* turned by hand: an arrow just inside the picture's edge, only the way there is to go, and two dots on its
   bottom-right corner, over the link; a card turned stays where it was put (data-shows, stalls.js) */
.turn{position:absolute;z-index:1;top:calc(var(--band) / 2 - 22px);display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;
  border-radius:50%;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:opacity .2s,visibility .2s}
.turn::before{content:'';width:36px;height:36px;border-radius:50%;background:rgb(29 26 47 / .78);transition:background .15s}
.turn:hover::before{background:var(--ink)}
.turn svg{position:absolute;width:12px;height:12px;fill:none;stroke:#fff;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.prev{left:4px}
.next{right:4px}
.dots{position:absolute;z-index:1;right:0;top:calc(var(--band) - 32px);display:flex;padding:0 4px;
  border-radius:8px 0 0 0;background:rgb(29 26 47 / .78)}
.dot{display:grid;place-items:center;width:28px;height:32px;padding:0;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.dot::before{content:'';width:8px;height:8px;border-radius:50%;background:#fff;opacity:.45;transition:opacity .2s}
.dot:focus-visible{outline:2px solid #fff;outline-offset:-4px;border-radius:6px}
.prev,[data-shows=home] .next{opacity:0;visibility:hidden}
[data-shows=home] :is(.home,.prev),.stall:not([data-shows=home]) .dot[data-to=stall]::before,[data-shows=home] .dot[data-to=home]::before{opacity:1;visibility:visible}
/* until it's turned by hand a stall turns by itself like the cards above, 6 s each, the picture crossfading in 0.6 s,
   each stall a beat (--turn) after the one before; with reduced motion it stays, and a turn by hand changes at once */
@keyframes home-in{0%,45%{opacity:0;visibility:hidden}50%,95%{opacity:1;visibility:visible}100%{opacity:0;visibility:hidden}}
@keyframes home-out{0%,45%{opacity:1;visibility:visible}50%,95%{opacity:0;visibility:hidden}100%{opacity:1;visibility:visible}}
@keyframes dot-in{0%,45%{opacity:.45}50%,95%{opacity:1}100%{opacity:.45}}
@keyframes dot-out{0%,45%{opacity:1}50%,95%{opacity:.45}100%{opacity:1}}
@media (prefers-reduced-motion:no-preference){
  .stall:is(:has(a.go):hover,:has(.go:focus-visible),.stirred) .drawn{animation:stir 1.52s steps(4) infinite}
  .stall[data-turns]:not([data-shows]) :is(.home,.prev),.stall[data-turns]:not([data-shows]) .next{animation:12s linear calc(var(--turn) - 1.4s) infinite both}
  .stall[data-turns]:not([data-shows]) :is(.home,.prev){animation-name:home-in}
  .stall[data-turns]:not([data-shows]) .next{animation-name:home-out}
  .stall[data-turns]:not([data-shows]) .dot::before{animation:12s linear calc(var(--turn) - 1.4s) infinite both}
  .stall[data-turns]:not([data-shows]) .dot[data-to=stall]::before{animation-name:dot-out}
  .stall[data-turns]:not([data-shows]) .dot[data-to=home]::before{animation-name:dot-in}
  [data-shows] .home{transition:opacity .6s linear}
}
@media (prefers-reduced-motion:reduce){.stall,.drawn,.turn,.dot::before{transition:none}}
.season-in{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-l);align-items:center}
.season-go{margin-top:var(--space-m)}
/* the glasshouse is drawn at 1 and shown at 2 on every screen, like every drawing on the shop (*Drawings in one style*):
   on a screen narrower than it, its edges are cut round the sign and the door (x 205 of its 400), never the page widened */
.season{overflow-x:clip}
.glasshouse{position:relative;margin:0 0 0 calc(50% - 410px);width:800px;height:520px}
.glasshouse img{width:800px;height:520px}
.glasshouse .train{position:absolute;z-index:2;display:none;pointer-events:none;animation:train 2.4s steps(12) infinite;image-rendering:pixelated}
@keyframes train{to{background-position:var(--trainEnd) 0}}
.soon-grid .pname{font-size:16px}
/* the "let me know" button follows an idea's line, and the buttons stand level along a row: each card's picture, words and button sit in its row's three shared tracks, so a row of one-line ideas has
   no empty line above its buttons, and one two-line idea moves its neighbours' buttons down with its own. The cards
   have no box, so an open one only lengthens its row. A browser without subgrid keeps room for two lines */
.soon-grid .scard{display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:0;align-content:start}
@supports not (grid-template-rows:subgrid){.soon-grid .pshort{min-height:calc(2 * 1.35em)}}
.promises{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr;gap:16px 14px}
.promises li{display:flex;flex-direction:column;gap:2px;padding-left:18px;position:relative;font-size:15px;line-height:1.4;color:var(--muted)}
/* the bold lines one size up, so they read as headings over their text; the square stays centred on the first line */
.promises li::before{content:'';position:absolute;left:0;top:9px;width:9px;height:9px;background:var(--amber)}
.promises b{color:var(--night);font-size:18px;line-height:1.5}

/* ---------------------------------------------------------------- lists: offers, all, search, an occasion, a kind */
.list{padding-bottom:var(--space-2xl)}
.list h1{margin-top:4px}

.wrap.narrow{padding-top:var(--space-l);padding-bottom:var(--space-2xl)}

/* ---------------------------------------------------------------- About us: today's onlyonery.com */
.about-page .hero{overflow-x:clip}
.hero-in{display:grid;gap:8px;padding-top:6px;padding-bottom:24px}
.hero-in h1{font-size:38px}
.art{position:relative;order:-1;display:block;width:auto;height:470px;margin:0 calc(-1 * var(--gutter));overflow:hidden;padding:0;border:0;background:none;font:inherit;color:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}
.art::before,.art::after{content:'';position:absolute;inset:10px 10px 40px;border-radius:50%;transition:opacity .6s}
.art::before{background:radial-gradient(closest-side,var(--sky) 0%,var(--sky2) 62%,rgba(234,245,253,0) 100%)}
.art::after{background:radial-gradient(closest-side,#3b3372 0%,#2a2352 60%,rgba(42,35,82,0) 100%);opacity:0}
/* the street is drawn at 1 and shown at 2, like every drawing on the shop (*Drawings in one style*): a phone sees it
   cropped to the roof sign and the corner's shop windows, a wider screen whole */
.art img{position:absolute;z-index:1;left:50%;margin-left:-445px;top:-125px;width:860px;height:862px}
.art .night{opacity:0;transition:opacity .6s steps(6)}
.art.lit .night,.art.lit::after{opacity:1}
.art.lit::before{opacity:0}
.about-page section{padding-block:var(--section)}
.us-in{display:grid;gap:28px}
.window{position:relative;height:340px;border-radius:24px;overflow:hidden;background:linear-gradient(#1d1a3f,#2a2352 55%,#3b3372)}
.window i{position:absolute;width:4px;height:4px;background:var(--gold-lt)}
.window i:nth-child(3n){background:#5a5290}
.window img{position:absolute;left:50%;margin-left:-450px;top:-120px;width:860px;height:862px}
.ticks{list-style:none;padding:0;margin:18px 0 0;display:grid;gap:12px}
.ticks li{display:grid;grid-template-columns:22px 1fr;gap:10px;align-items:baseline}
.ticks li::before{content:'';width:9px;height:9px;background:var(--night);transform:translateY(-1px)}
/* About us: buying from us, under who we are (the trust lines, in the shop's own pages' words) */
.trust{grid-template-columns:1fr;margin-top:var(--space-2xl)}
/* who prints it: Print API's works in Groningen, drawn like the glasshouse and shown at 2 like it: a narrower screen sees
   it cut round the press, the cutter and the van (x 230 of its 400) */
.printer{overflow-x:clip}
.printer-in{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-l);align-items:center}
.printer-in p{color:var(--muted);max-width:640px}
.printworks{margin:0 0 0 calc(50% - 460px);width:800px;height:520px}
.printworks img{width:800px;height:520px}
.hello-box{display:grid;gap:22px;background:#fff;border-radius:22px;padding:26px 22px;box-shadow:0 0 0 1px var(--line)}
.hello-box p:not(.label){margin:0;color:var(--muted)}
.bell{display:flex;align-items:center;gap:16px;padding:6px;margin:18px 0 0 -6px;font:inherit;color:inherit;background:none;border:0;border-radius:12px;cursor:pointer;-webkit-tap-highlight-color:transparent;text-align:left}
.bell-art svg{width:52px;height:68px}
.bell .ringlabel{font-weight:700}
.bell .led{fill:#6b4e1b}
.ringing .bell .led{fill:var(--lamp)}
.reply{position:relative;padding:16px 20px;border-radius:16px;background:var(--paper);box-shadow:inset 0 0 0 2px var(--line);min-height:120px}
.reply::before{content:'';position:absolute;inset:20px 8px 8px 20px;background:conic-gradient(at 4px 4px,#0000 75%,var(--line) 0) 0 0/16px 16px space;opacity:0;pointer-events:none}
.reply.quiet::before{opacity:1}
.reply.quiet>*{visibility:hidden}
.reply p{margin:0 0 8px;color:var(--night)}
.reply p:last-child{margin:0}
.reply .crackle{font-style:italic;color:var(--muted);letter-spacing:.1em;font-size:15px}
.ringing .reply>*{animation:up .35s .4s both}
@keyframes up{from{opacity:0;transform:translateY(6px)}}

/* ---------------------------------------------------------------- the letter: its sign-up, last on every page, into the footer */
.letter-in{display:grid;gap:var(--space-l)}
.letter-say p:last-child{margin:0;color:var(--muted);max-width:560px}
.letter-row{display:flex;flex-direction:column;gap:var(--space-s)}
.letter-row input{flex:1;min-width:0}
.letter-err{margin:var(--space-xs) 0 0;color:var(--sale);font-size:15px;font-weight:700}
.letter-err:empty{display:none}
.letter-small{margin:var(--space-s) 0 0;font-size:15px;line-height:1.5;color:var(--muted)}
.letter-thanks{margin:0;padding:var(--space-m) var(--space-l);background:#fff;border-radius:12px;box-shadow:inset 0 0 0 2px var(--line)}
.letter-thanks:focus{outline:none}
.leave-form .f{display:flex;flex-direction:column;gap:4px;max-width:480px;font-size:15px;font-weight:700}
.leave-form .btn{margin-top:var(--space-m)}
@media (min-width:480px){.letter-row{flex-direction:row}}
/* the sign-up as wide as its privacy line in the page's language, where the screen has room, so the line keeps to one
   line; the words beside it keep at least 400 px */
@media (min-width:1100px){.letter-in{grid-template-columns:minmax(400px,1fr) fit-content(800px);align-items:center;gap:var(--space-3xl)}}

/* ---------------------------------------------------------------- the footer: the cat asleep on its edge */
.foot{position:relative;background:var(--ink);color:#d9d3ea;margin-top:var(--space-3xl);padding:36px 0 26px}
.foot .pet{position:absolute;top:-48px;right:28px;width:56px;height:48px;padding:0;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.foot .cat{width:56px;height:48px}
.heart{position:absolute;left:26px;top:-28px;width:28px;height:24px;pointer-events:none;animation:heart 1.2s steps(9) both}
@keyframes heart{0%{opacity:0;transform:translateY(8px)}15%,65%{opacity:1}to{opacity:0;transform:translateY(-28px)}}
.foot .cols{display:grid;grid-template-columns:1fr 1fr;gap:26px 18px}
.foot .brand{grid-column:1/-1}
.foot .wm{width:198px;height:34px;margin-bottom:12px}
/* margin-block only: the AI line and the company line are .wrap, centred by their inline margins (note #35) */
.foot p{margin-block:0;font-size:15px}
/* where the page ends in the letter's band, the footer meets it and the cat sleeps on the seam */
main:has(> .letter:last-child) + .foot{margin-top:0}
.foot nav{display:flex;flex-direction:column;gap:2px}
.foot h2{font-size:15px;margin:0 0 4px;color:#fff}
.foot nav a{color:#d9d3ea;font-size:15px;text-decoration:none;min-height:36px;display:flex;align-items:center}
.foot nav a:hover{color:var(--lamp);text-decoration:underline}
.foot .ai{margin-top:26px;font-size:14px;color:#b9b2d2}

/* ---------------------------------------------------------------- stepping into a stall: a soft fade under its sign */
/* the stall's page starts from the same colour (bar.js #oy-door): keep the two in step */
.door{position:fixed;inset:0;z-index:900;pointer-events:none;background:var(--glass);opacity:0;transition:opacity .2s ease-out}
.door.shut{opacity:1}
/* the stall's mark and name in the middle of its colour (bar.js .oy-door-mark draws the same, in the same place) */
.door-mark{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}

/* ---------------------------------------------------------------- 5. basket and checkout */
.lines{display:grid;gap:14px;margin:8px 0 22px}
.line{display:grid;gap:14px;padding:14px;border-radius:16px;background:#fff;box-shadow:0 0 0 1px var(--line)}
.line .from{display:flex;align-items:center;gap:7px;font-size:14px;font-weight:700;color:var(--muted);margin:0}
.line h3{font-size:18px;line-height:1.25;margin:4px 0 2px}
.line p{margin:0;font-size:15px;color:var(--muted);line-height:1.4}
.line .row{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:8px}
.line .row b{font-size:17px}
.line .acts{display:flex;gap:4px}
.line .acts a,.line .acts button{font:inherit;font-size:15px;color:var(--brass);background:none;border:0;padding:8px 6px;min-height:44px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
/* one thing in the basket: one quiet line, and a few things from the other stalls */
.invite{margin:-8px 0 22px}
.invite p{margin:0 0 10px;font-size:15px;color:var(--muted);line-height:1.45}
.picks{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px}
/* a row's picks all as tall as its tallest, so a name that wraps doesn't make one stand out */
.picks li{display:flex}
.picks a{flex:1;display:flex;align-items:center;gap:12px;padding:8px;border-radius:12px;background:#fff;box-shadow:0 0 0 1px var(--line);color:var(--night);text-decoration:none;min-height:44px}
.picks img{width:64px;height:48px;object-fit:cover;border-radius:8px;flex:none}
.picks span{display:grid;font-size:15px;line-height:1.3}
.picks .price{margin:0;font-size:14px;color:var(--muted)}
.picks .offer-note{font-size:13px;color:var(--sale)}
.sum{display:grid;gap:10px}
.total{display:flex;justify-content:space-between;align-items:baseline;font-size:20px;margin:0;border-top:2px solid var(--line);padding-top:16px}
.total b{font-size:26px}
.sum .fine{margin:0}
/* when it ships (the delivery only as an estimate) */
.ship{margin:4px 0 8px;padding:12px 14px;border-radius:12px;background:var(--paper2);font-size:15px;line-height:1.5}
.ship p{margin:0}
.ship p+p{margin-top:4px;color:var(--muted)}
.keep{text-align:center;padding:10px;font-size:16px}
.empty{padding:16px 0}
.step{display:flex;align-items:center;gap:12px;font-size:23px;margin:30px 0 8px}
.step span{display:grid;place-items:center;width:32px;height:32px;border-radius:50%;background:var(--night);color:var(--paper);font-size:17px;flex:none}
.fields{display:grid;grid-template-columns:1fr 1fr;gap:10px 12px;margin-top:10px}
.fields .f{display:flex;flex-direction:column;gap:4px;font-size:15px;font-weight:700}
.fields .f.wide{grid-column:1/-1}
/* Trustpilot's one email, said under the address it goes to, with the box to say no (unticked) */
.fields .review{grid-column:1/-1}
.review .fine{margin:2px 0 0}
.tick{display:flex;align-items:center;gap:12px;min-height:48px;font-size:16px;font-weight:700;cursor:pointer}
.tick input{flex:none;width:24px;height:24px;min-height:0;margin:0;padding:0;accent-color:var(--night);cursor:pointer}
/* the address filled in from this device, and the one quiet button that forgets it */
.fields .kept{grid-column:1/-1;margin:-6px 0 0}
.kept button{font:inherit;font-size:15px;color:var(--brass);background:none;border:0;padding:8px 0;min-height:44px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.delivery{display:grid;gap:10px;margin:0 0 14px}
/* a code or a voucher: one field; once a code is on, its name, what it saves and its terms */
.code{margin:0 0 4px}
.codeform{display:flex;align-items:flex-end;gap:10px;margin:4px 0 8px}
.codeform .f{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0;font-size:15px;font-weight:700}
.codeform input{text-transform:uppercase;letter-spacing:.06em}
.codeform .btn{flex:none}
.codeon{display:grid;gap:4px;padding:12px 14px;border-radius:12px;background:var(--paper2)}
.codeline{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;margin:0;font-size:16px}
.codeline span{color:#3f6630;font-weight:700}
.codeline button{margin-left:auto;font:inherit;font-size:15px;color:var(--brass);background:none;border:0;padding:8px 0;min-height:44px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.codeon .fine{margin:0;font-size:14px}
.err{color:#9b2c2c;font-weight:700;min-height:0;margin:0 0 10px}
.err:empty{display:none}

/* ---------------------------------------------------------------- 6. done */
.thanks{position:relative;padding-top:28px}
/* a test order's one small mark (the shop's test code): the rest of the page is a customer's */
.thanksrow{display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px;min-height:24px;margin:0 0 12px}
.thanksrow .label{margin:0}
.testmark{display:inline-block;margin:0;padding:2px 10px;line-height:20px;border-radius:999px;background:var(--paper2);color:var(--muted);font-size:14px}
/* our shop at night in today's season (kits/cards/designs/shop.js, drawn by cardpick.js): its lights come on once the payment is in */
/* drawn at 216 x 128 and shown at 2 on every screen (*Drawings in one style*): a box narrower than its 432 px crops its
   sides round the shop, the drawing and its sky centred on whole pixels */
.shopnight{position:relative;width:min(100%,432px);height:256px;margin:0 0 18px;border-radius:14px;overflow:hidden;background:var(--night)}
.shopnight > svg,.sky{position:absolute;top:0;left:calc(50% - 216px);left:round(50% - 216px,1px);width:432px;height:256px}
.shopnight > svg{display:block}
.cfscene svg,.cfmark svg,.dscene svg{display:block;width:100%;height:auto}
.shopnight path[data-light]{transition:fill 1.4s ease-out}
.shopnight:not(.lit) path[data-light=lamp]{fill:#5a5478}
.shopnight:not(.lit) path[data-light=bulb]{fill:#4f4670}
/* the weather over it, a flake one or two of its pixels, falling and drifting in whole ones (cardpick.js places them) */
.sky{pointer-events:none}
.sky i{position:absolute;left:var(--x);top:-4px;width:2px;height:2px;background:var(--paper);animation:fall var(--fall) steps(65) var(--delay) infinite,drift calc(var(--fall) / 3) steps(2) var(--delay) infinite alternate}
.sky i:nth-child(3n){width:4px;height:4px}
[data-season=spring] .sky i{width:4px;background:#ff8fab}
[data-season=autumn] .sky i{width:4px;background:#c97c14}
[data-season=autumn] .sky i:nth-child(2n){background:#c0593f}
[data-season=summer] .sky i{top:var(--y);background:var(--lamp);animation:glow calc(var(--fall) / 2) steps(2) var(--delay) infinite}
@keyframes fall{to{transform:translateY(260px)}}
@keyframes drift{to{translate:4px 0}}
@keyframes glow{0%,100%{opacity:0}40%,60%{opacity:1;transform:translate(4px,-4px)}}
/* the card in the parcel: its front as it prints, cut at the trim (98 x 98 mm: the words 8 mm from the fold and 9 mm
   from the top, the logo 6 mm from the right and 11 mm down, 22 mm wide, the picture from 5 mm round the fold and 37 mm down).
   Its pictures are drawn a pixel a millimetre, so the card is shown at a whole number of CSS pixels a millimetre (--mm):
   3 on a phone, 4 from 700 px, 2 on a phone too narrow for 3. The logo aims at its printed 22 mm (--mark, one of its
   pixels), and cardpick.js moves that to the nearest whole number of the screen's own pixels, at least one (the
   brand's 99-pixel minimum): 2 on a 3x phone (as printed), 1 on a 2x one, 1 CSS pixel on a 1x screen. The words keep
   2 mm clear of the logo's width as shown, or go under it on a 1x screen too narrow for both side by side */
/* the surprise in a panel of its own, apart from the order's own facts, so the page reads as three parts: thanks, the
   card, the order */
.cardpick{margin:var(--space-l) 0 0;padding:var(--space-m) clamp(16px,4vw,28px) clamp(16px,4vw,24px);border-radius:18px;background:var(--paper2)}
@media (max-width:399px){.cardpick{padding-inline:12px}}
.cardpick h2.sub{margin-top:0}
/* the card's terms, small print under its few words */
.cardpick .cardterms{margin:calc(-1 * var(--space-s)) 0 var(--space-m);font-size:14px;line-height:1.45}
.cardstage{position:relative;display:grid;justify-items:center;margin:18px 0 16px;perspective:900px;transition:padding .5s ease}
.cardfront{--mm:3px;--mark:calc(22 * var(--mm) / 99);position:relative;container-type:inline-size;width:calc(98 * var(--mm));aspect-ratio:1;overflow:hidden;border-radius:3px;background:var(--night);color:var(--paper);box-shadow:0 10px 24px rgba(29,26,47,.22);transition:transform .6s cubic-bezier(.3,.7,.3,1)}
.cfwords{position:absolute;left:calc(8 * var(--mm));right:calc(8 * var(--mm) + 99 * var(--mark));top:calc(9 * var(--mm))}
.cardfront p{margin:0}
.cf1{font:700 7.55cqw/1.1 var(--sans)}
.cfmark{position:absolute;right:calc(6 * var(--mm));top:calc(11 * var(--mm));width:calc(99 * var(--mark))}
.cfscene{position:absolute;left:calc(-5 * var(--mm));top:calc(37 * var(--mm));width:calc(108 * var(--mm));aspect-ratio:108/64;overflow:hidden}
@media (max-width:357px){.cardfront{--mm:2px}}
/* a 1x screen that narrow: the logo's 99 screen pixels are half the card, so the words go under it */
@media (max-width:357px) and (max-resolution:1.49dppx){.cfmark{top:calc(8 * var(--mm))}.cfwords{right:calc(6 * var(--mm));top:calc(10 * var(--mm) + 17 * var(--mark))}}
@media (min-width:700px){.cardfront{--mm:4px}}
/* the spin (cardpick.js): a reel of one picture and the next above it, rolled down by cardpick.js; while it rolls the
   window's top edge fades into the night (a gradient fade: a mask here crashes headless Chromium's screenshots), so the
   pictures come out of the sky rather than from behind a line */
.reel{position:relative;will-change:transform}
.cfnext{position:absolute;left:0;right:0;bottom:100%}
.cfscene.rolling::before{content:'';position:absolute;inset:0 0 auto;z-index:1;height:22%;background:linear-gradient(var(--night),transparent)}
.cardfront.turn{animation:turn .4s ease-out}
@keyframes turn{from{transform:rotateY(-75deg)}to{transform:none}}
.cardfront.landed{animation:landed .45s cubic-bezier(.3,.7,.3,1)}
@keyframes landed{40%{transform:translateY(-6px) scale(1.03)}}
.cardbtns{justify-content:center;margin-top:6px}
/* the pop-up of every picture: a sheet from the bottom on a phone, a card in the middle from 600 px, three to a row */
.carddeck{--dk:1px;width:min(100% - 32px,600px);max-height:min(88vh,760px);padding:0;border:0;border-radius:18px;background:var(--paper);color:var(--night);box-shadow:0 18px 48px rgba(29,26,47,.35);overflow:auto;overscroll-behavior:contain}
.carddeck::backdrop{background:rgba(29,26,47,.55)}
.carddeck[open]{animation:deck .3s cubic-bezier(.3,.7,.3,1)}
@keyframes deck{from{transform:translateY(32px);opacity:0}}
@media (max-width:599px){.carddeck{width:100%;max-width:100%;max-height:86vh;margin:auto 0 0;border-radius:18px 18px 0 0}}
.deckhead{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 12px 10px 18px;background:var(--paper)}
.deckhead h3{margin:0;font:700 20px/1.2 var(--sans)}
.deckx{flex:none;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:var(--paper2);color:var(--night);font:700 26px/1 var(--sans);cursor:pointer}
/* each picture at a whole pixel a millimetre (--dk): 1 in a phone's sheet, 2 in the wider card from 760 px, its tile
   just round it, as many to a row as fit */
.designs{display:grid;grid-template-columns:repeat(auto-fill,calc(108 * var(--dk) + 6px));justify-content:center;gap:10px 6px;padding:2px 16px calc(18px + env(safe-area-inset-bottom))}
@media (min-width:760px){.carddeck{--dk:2px;width:min(100% - 32px,720px)}.designs{gap:10px}}
.design{display:block;padding:0 0 8px;border:3px solid transparent;border-radius:12px;background:var(--night);color:var(--paper);font:700 14px/1.2 var(--sans);text-align:center;cursor:pointer;overflow:hidden;overflow-wrap:anywhere}
.design[aria-pressed=true]{border-color:var(--lamp);box-shadow:0 0 0 2px var(--night)}
.design:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.dname{display:block;padding:6px 4px 0}
.swatches{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px;margin:6px 0 10px}
.swatches[hidden]{display:none}
.swatches span{margin-right:6px;font-size:15px;font-weight:700}
.swatch{width:44px;height:44px;padding:0;border:2px solid var(--ink);border-radius:50%;background:var(--swatch);box-shadow:inset 0 0 0 3px rgba(255,250,240,.35);cursor:pointer}
.swatch[aria-pressed=true]{outline:3px solid var(--night);outline-offset:3px}
/* the colours, buttons and swap line sit centred under the card, like the card itself */
.cardopts{text-align:center;transition:opacity .4s ease}
.cardopts.going{opacity:0}
.cardsoon{margin:14px 0 0}
/* a cup of coffee that empties over the time left: the only clock on the page. A white cup, the coffee dark inside
   its walls; inline with the words, so a line that wraps stays centred with its cup */
.cup{position:relative;display:inline-block;vertical-align:-2px;width:16px;height:14px;margin:0 20px 0 0;border:2px solid var(--night);border-top:0;border-radius:0 0 4px 4px;background:#fff;overflow:visible}
.cup::after{content:'';position:absolute;right:-7px;top:2px;width:4px;height:6px;border:2px solid var(--night);border-left:0;border-radius:0 4px 4px 0}
.cup::before{content:'';position:absolute;left:5px;top:-11px;width:2px;height:6px;background:var(--muted);opacity:.6;animation:steam 2.4s steps(3) infinite}
.cup i{position:absolute;left:0;right:0;bottom:0;height:100%;border:2px solid #fff;border-top:0;background:#4a2b14}
@keyframes steam{from{transform:translate(0,4px);opacity:0}50%{opacity:.6}to{transform:translate(2px,-4px);opacity:0}}
/* the parcel's front is drawn 180 x 55 and shown at 2; a column narrower than it cuts its sides */
.parcelbox{position:absolute;bottom:0;z-index:1;display:flex;justify-content:center;width:min(100%,360px);overflow:hidden;opacity:0;transform:translateY(24px);transition:opacity .4s ease .25s,transform .5s ease .25s;pointer-events:none}
.tucked .cardstage,.tucked-still .cardstage{padding-bottom:78px}
.tucked .cardfront,.tucked-still .cardfront{transform:translateY(10%) scale(.82) rotate(-2deg)}
.tucked .parcelbox,.tucked-still .parcelbox{opacity:1;transform:none}
.tucked-still .cardstage,.tucked-still .cardfront,.tucked-still .parcelbox{transition:none}
.parcelbox svg{flex:none;display:block;width:360px;height:110px}
.cardset{margin:0;text-align:center;font-weight:700}
.next{padding:0;margin:0 0 var(--space-m);list-style:none;counter-reset:n}
.next li{position:relative;display:flex;gap:14px;padding:0 0 18px;line-height:1.5;counter-increment:n}
.next li::before{content:counter(n);flex:none;display:grid;place-items:center;width:28px;height:28px;margin-top:-2px;border-radius:50%;background:var(--night);color:var(--paper);font-size:15px;font-weight:700}
.next li:not(:last-child)::after{content:'';position:absolute;left:13px;top:30px;bottom:2px;width:2px;background:var(--line)}
#doneShip .ship{margin:14px 0 0}
/* the send-off over the shop at night (sendoff.js, on the scene's grid, so a px is one of its pixels): once the payment is
   in, the parcel hops from the door into the courier's box, the bike settles and rides off, once, about 5 s in all.
   With reduced motion the parcel is in the box and the bike stays */
.sendoff{pointer-events:none}
.sendoff .hop,.sendoff .inbox,.sendoff .legs1{opacity:0}
.going .hop{animation:hop 1.6s steps(1) .6s both}
.going .inbox{animation:show 0s 2.2s both}
.going .bounce{animation:settle .3s steps(1) 2.2s}
.going .ride{animation:ride 2.6s 2.5s both}
.going .legs0{animation:pedal .36s steps(1) 2.5s 8 reverse}
.going .legs1{animation:pedal .36s steps(1) 2.5s 8}
@keyframes hop{0%{opacity:0;transform:translate(0,2px)}10%{opacity:1;transform:translate(0,1px)}20%,45%{opacity:1;transform:none}49%{transform:translate(5px,-5px)}53%{transform:translate(9px,-9px)}57%{transform:translate(14px,-12px)}61%{transform:translate(18px,-14px)}65%{transform:translate(23px,-14px)}69%{transform:translate(27px,-14px)}73%{transform:translate(32px,-12px)}77%{transform:translate(36px,-10px)}81%{transform:translate(41px,-6px)}85%,99.9%{opacity:1;transform:translate(45px,-1px)}100%{opacity:0;transform:translate(45px,-1px)}}
@keyframes show{to{opacity:1}}
@keyframes settle{0%{transform:translateY(1px)}}
/* down the street's slope, 2 px left for 1 down a step, slowly at first, till it's out of the picture */
@keyframes ride{0%{transform:none;animation-timing-function:steps(4)}40%{transform:translate(-8px,4px);animation-timing-function:steps(8)}70%{transform:translate(-24px,12px);animation-timing-function:steps(30)}to{transform:translate(-84px,42px)}}
@keyframes pedal{0%{opacity:1}50%{opacity:0}}
@media (prefers-reduced-motion:reduce){.going .inbox{opacity:1}}
/* a line in the basket: what's on it, its price, what one parcel or a voucher takes off, and its order page in its stall */
.lprice{display:flex;align-items:baseline;gap:8px}
.line .notes{margin-top:4px;color:#3f6630;font-weight:700}
.line .detail{color:var(--ink);font-size:16px}
.line .see a{display:inline-block;padding:8px 0;min-height:44px;box-sizing:border-box;font-size:15px}
.line .row{flex-wrap:wrap}
/* each thing's little picture beside it: its own design from its stall (lines.js designOf), laid on a scrap of paper,
   or on the thank-you page its kind's (thumbOf) */
.line.thumbed{grid-template-columns:96px 1fr;align-items:start}
.line .thumb{display:grid;place-items:center;width:96px;height:72px;border-radius:10px;object-fit:cover;box-shadow:0 0 0 1px var(--line)}
.line .pic{display:grid;place-items:center;width:96px;height:96px;border-radius:12px;background:var(--paper2);box-shadow:0 0 0 1px var(--line)}
.line .pic img{display:block;max-width:80px;max-height:80px;object-fit:contain;transform:rotate(-2deg);filter:drop-shadow(0 2px 3px rgba(60,40,10,.22));transition:transform .25s}
.line a.pic:hover img{transform:rotate(0) scale(1.05)}
@media (max-width:359px){.line.thumbed{grid-template-columns:72px 1fr}.line .thumb{width:72px;height:54px}.line .pic{width:72px;height:72px}.line .pic img{max-width:60px;max-height:60px}}
@media (prefers-reduced-motion:reduce){.line .pic img{transition:none}}
/* a parcel gift magnet under its thing: smaller, tied to it by a little bracket, its tile, its words, Free or its price */
.line.magnet{position:relative;grid-template-columns:auto 1fr auto auto;align-items:center;gap:6px 12px;margin:-6px 0 0 26px;padding:6px 8px 6px 12px;border-radius:12px;background:var(--paper2);box-shadow:none}
.line.magnet::before{content:'';position:absolute;left:-16px;top:-14px;width:12px;height:calc(50% + 14px);border:solid var(--line);border-width:0 0 2px 2px;border-bottom-left-radius:8px}
.line.magnet .tile{display:block;width:22px;height:22px}
.line.magnet .tile svg{display:block}
.line.magnet .what{color:var(--ink);font-size:15px}
.line.magnet .lprice b{font-size:15px}
.line.magnet .notes{grid-column:2 / -1}
@media (max-width:519px){
  .line.magnet{grid-template-columns:auto 1fr auto;margin-left:18px}
  .line.magnet::before{left:-12px;width:8px}
  .line.magnet .tile{grid-row:span 2;align-self:start;margin-top:4px}
  .line.magnet .what{grid-column:2 / -1}
}
.note{margin:0 0 12px;padding:10px 12px;border-radius:10px;background:var(--paper2);font-size:15px}
.wait{margin:8px 0 18px}
/* the thank-you page's wait keeps the page's room, so the order comes in below it rather than pushing the foot down; not once the payment is slow */
#doneWait{min-height:60vh}
#doneWait.slow{min-height:0}
.pay-note{margin:10px 0 0;text-align:center}

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

/* ---------------------------------------------------------------- 7. Your orders, and ordering again from a backup file */
/* the envelope the code comes in hops off once it's sent; each order is a till slip from the shop's own roll */
.orders-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;overflow-x:clip}
.orders-head h1{margin-bottom:8px}
.mail{flex:none;display:block;width:64px;height:48px;margin:0 6px 10px 0}
.mail.off svg{animation:posted 1.1s cubic-bezier(.5,0,.3,1) both}
@keyframes posted{0%{transform:none}25%{transform:translateY(-10px) rotate(-6deg)}100%{transform:translate(60px,-34px) rotate(14deg);opacity:0}}
.signin{display:grid;gap:12px;max-width:480px;margin:6px 0 0}
.signin .f{display:flex;flex-direction:column;gap:4px;font-size:15px;font-weight:700}
.signin .btn{justify-self:start}
.signin .intro,.signin .fine,.signin .err{margin:0}
#oCode{max-width:220px;font-size:24px;letter-spacing:.3em;font-variant-numeric:tabular-nums}
.sent{margin:0;padding:12px 14px;border-radius:12px;background:var(--paper2);font-size:16px;line-height:1.5;color:var(--ink)}
.sent:focus{outline:none}
.again{display:flex;flex-wrap:wrap;gap:0 18px}
.linkish{font:inherit;font-size:15px;color:var(--brass);background:none;border:0;padding:8px 0;min-height:44px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.slips{display:grid;gap:26px;margin:18px 0 22px}
.slip{background:#fff;padding:16px 18px 30px;box-shadow:0 1px 0 var(--line);transform:rotate(-.4deg);font-variant-numeric:tabular-nums;
  -webkit-mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/14px 100%;mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/14px 100%}
.slip.tilt{transform:rotate(.4deg)}
.slip header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;padding-bottom:10px;border-bottom:2px dashed var(--line)}
.slip .when{margin:0;font-weight:700;color:var(--night)}
.slip ul{list-style:none;margin:0;padding:0}
.slip .thing{display:grid;gap:4px;padding:14px 0;border-bottom:1px dashed var(--line)}
.slip .from{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:0;font-size:14px;font-weight:700;color:var(--muted)}
.slip h3{font-size:18px;line-height:1.25;margin:2px 0 0;overflow-wrap:anywhere}
.slip .thing p{margin:0;font-size:15px;line-height:1.4;color:var(--muted)}
.slip .detail{overflow-wrap:anywhere}
.slip .row{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:4px}
.slip .row b{font-size:17px;color:var(--night)}
.slip .chip{background:var(--paper2);font-size:13px}
.slip .chip.st-cancelled,.slip .chip.refund{color:var(--sale)}
.slip .kept{color:var(--save)!important;font-weight:700}
.slip .see a,.slip .gone-note a,.slip .invoice,.fromfile a{color:var(--brass);text-underline-offset:3px}
.slip .see a{display:inline-flex;align-items:center;gap:6px;min-height:44px;font-weight:700}
.slip .gone-note{padding:8px 0 0}
.slip .gone-note span{display:block;color:var(--ink)}
.slip .gone-note a{display:inline-flex;align-items:center;min-height:44px}
.slip footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;padding-top:12px}
.slip .paid{display:flex;align-items:baseline;gap:10px;margin:0;font-size:17px}
.slip .paid b{font-size:22px;color:var(--night)}
.slip .invoice{display:inline-flex;align-items:center;min-height:44px;font-weight:700}
.signed{margin:0}
.fromfile{margin:var(--space-xl) 0 0}
.fromfile a{display:inline-flex;align-items:center;gap:12px;min-height:44px;font-weight:700}
.fromfile svg{flex:none;width:28px;height:28px}
/* the backup page: the file goes in at the drop, and shows itself before it's sent */
.drop{display:grid;justify-items:center;gap:10px;margin:8px 0 12px;padding:28px 18px;border:3px dashed var(--line);border-radius:18px;background:#fff;text-align:center;cursor:pointer;transition:border-color .15s,background .15s}
.drop:hover,.drop.over,.drop:focus-within{border-color:var(--night);background:var(--sky2)}
.drop svg{width:70px;height:70px}
.drop:hover svg,.drop.over svg{animation:nudge .5s ease-out}
@keyframes nudge{40%{transform:translateY(-6px) rotate(-3deg)}}
.drop-go{display:inline-flex;align-items:center;min-height:48px;padding:12px 22px;border-radius:99px;background:var(--night);color:var(--paper);font-weight:700;font-size:17px}
.drop:hover .drop-go{background:var(--ink)}
.drop .fine{margin:0;max-width:34ch}
.picked{display:grid;gap:18px;align-items:start;margin:8px 0 12px}
.frame{margin:0;justify-self:center;padding:10px;background:#fff;box-shadow:0 0 0 1px var(--line),0 4px 0 var(--line);transform:rotate(-1.2deg);max-width:280px}
.frame img{display:block;width:100%;height:auto}
.picked .from{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 6px;font-size:19px;font-weight:700;color:var(--night)}
.picked .from svg{width:128px;height:40px}
.picked .fine{margin:0 0 14px}
.picked p:last-child{margin:6px 0 0}
.tips{margin:0;padding-left:1.2em;color:var(--muted);font-size:16px;line-height:1.5}
.tips li+li{margin-top:6px}
.backup>.fine:last-child{margin-top:var(--space-l)}
@media (min-width:640px){.picked{grid-template-columns:240px minmax(0,1fr)}}

/* ---------------------------------------------------------------- tablet (800) */
@media (min-width:700px){
  body{font-size:18px}
  h1{font-size:44px}
  h2{font-size:32px}
  .bar{padding-right:var(--edge)}
  .search{margin-right:0}
  /* the ways in as much room under the awning (16 px over the page) as above the news band */
  .ways{padding-top:calc(16px + var(--space-m));padding-bottom:var(--space-m)}
  .nav>a:not(.basket-btn):not(.chat-btn){font-size:16px;padding:0 12px}
  .grid{grid-template-columns:repeat(3,1fr);gap:var(--space-xl) var(--space-l)}
  .promo-in{padding-top:var(--space-l);padding-bottom:var(--space-l)}
  .promo h2{font-size:28px}
  .head-row h1{font-size:28px}
  .promises{grid-template-columns:repeat(3,1fr)}
  .trust{grid-template-columns:repeat(3,1fr)}
  /* each list as wide as its words and the same room between them (the board's note #59) */
  .foot .cols{grid-template-columns:repeat(4,auto);justify-content:space-between}
  .foot .pet{right:48px}
  .art{height:620px}
  .art img{margin-left:-430px;top:-120px}
  .art::before,.art::after{inset:0 60px 30px}
  .window{height:420px}
  .window img{margin-left:-430px;top:-140px}
  .hello-box{grid-template-columns:1fr 1fr;padding:40px;align-items:center}
  .picks{grid-template-columns:repeat(3,1fr)}
}

/* ---------------------------------------------------------------- laptop (1408 x 650): search in the top bar */
@media (min-width:1100px){
  /* one row again: the logo's row takes the wrapper's three columns (a subgrid), the search the middle one. The page
     column's edges are the wrapper's own padding: on the subgrid, a percentage padding sizes its columns as if the
     window were narrow, so on a wide screen the logo's column shrank to nothing under the search */
  .top{display:grid;grid-template-columns:auto 1fr auto;column-gap:28px;align-items:center;padding:0 var(--edge)}
  .shopbar{grid-area:1/1/2/-1;display:grid;grid-template-columns:subgrid;gap:28px;min-height:72px;padding:0}
  .nav{grid-column:3}
  .searchbar{grid-area:1/2;padding:0}
  .search{margin:0}
  .grid{grid-template-columns:repeat(4,1fr)}
  .soon-grid{grid-template-columns:repeat(4,1fr)}
  .foot .cols{grid-template-columns:minmax(0,340px) repeat(4,auto)}
  .foot .brand{grid-column:auto}
  .season-in{grid-template-columns:800px 1fr;gap:40px}
  .glasshouse{margin:0}
  .hero-in{grid-template-columns:480px 1fr;align-items:center}
  .art{order:0;margin:0;height:600px}
  .art img{top:-140px}
  .us-in{grid-template-columns:520px 1fr;gap:56px;align-items:center}
  .printer-in{grid-template-columns:800px 1fr;gap:40px}
  .printworks{margin:0}
}
/* the laptop is only 650 px tall: wider pictures and a slimmer news band keep the prices on the first screen */
@media (min-width:1100px){.shelf .pimg,.list .pimg{aspect-ratio:4/3}.promo-in{padding-top:var(--space-s);padding-bottom:var(--space-s)}}
@media (min-width:1100px){
  .shopbar{min-height:64px}
  .promo-in{display:grid;grid-template-columns:auto 1fr;column-gap:24px;align-items:baseline}
  .promo .label{grid-row:span 2;margin:0}
  .promo h2{font-size:24px}
  .shelf .pimg,.list .pimg{aspect-ratio:16/10}
  .head-row h1{font-size:26px}
}

/* A whole product card on the first screen wherever the search wraps (the board, call #88: picture, name, price and
   "Make yours" say "shop" at a glance): on a phone the news band keeps its title and link;
   a tablet held sideways or a short laptop window gets the laptop's slim band and wider pictures. */
@media (max-width:699px){.promo-text{display:none}}
@media (min-width:700px) and (max-width:1099px) and (max-height:900px){
  .shelf .pimg,.list .pimg{aspect-ratio:16/10}
  .promo-in{display:grid;grid-template-columns:auto 1fr;column-gap:24px;align-items:baseline;padding-top:var(--space-s);padding-bottom:var(--space-s)}
  .promo .label{grid-row:span 2;margin:0}
  .promo h2{font-size:24px}
}
@media (min-width:900px) and (max-width:1099px) and (max-height:900px){.grid{grid-template-columns:repeat(4,1fr)}}

/* ---------------------------------------------------------------- the real shop: languages, Poppy's chat, a thing's page */
.strip{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 var(--edge);background:var(--night);color:var(--paper)}
.langs{display:flex;gap:2px;flex:none}
.strip-pause{display:none;flex:none;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:4px;background:none;color:var(--paper);fill:currentColor;opacity:.75;cursor:pointer}
.strip-pause:focus-visible{outline:2px solid var(--lamp);outline-offset:0;opacity:1}
.strip-pause .play-arrow,.strip-pause[aria-pressed=true] .pause-bars{display:none}
.strip-pause[aria-pressed=true] .play-arrow{display:inline}
.langs a{display:inline-flex;align-items:center;min-height:28px;padding:0 6px;color:var(--paper);font-size:14px;font-weight:700;text-decoration:none;opacity:.75}
.langs a[aria-current]{opacity:1;text-decoration:underline;text-decoration-color:var(--lamp);text-underline-offset:4px}
/* On a phone the strip's gaps close up and the pause button's hit area fills the gaps on either side of it, so it takes
   only 8 px of the line and Dutch's longest promise still fits on one from 390 px (its icon keeps 7 px clear inside) */
@media (max-width:699px){
  .strip{gap:var(--space-xs)}
  .langs a{padding:0 4px}
  .strip-pause{display:inline-flex;margin-inline:calc(-1 * var(--space-xs))}
}
/* Poppy's button is a chat, and looks like one (the board, call #70): a speech bubble and "Chat with Poppy". In the
   header beside the basket from a tablet up; on a phone, where the header has no room, a pill in the bottom corner */
.chat-btn{display:inline-flex;align-items:center;gap:7px;min-height:44px;padding:0 16px 0 12px;border-radius:99px;background:var(--night);color:var(--paper);
  font-size:15px;font-weight:700;text-decoration:none;white-space:nowrap;--bubble-dot:var(--night)}
.chat-btn .bubble{color:var(--lamp)}
.chat-btn:hover{background:var(--ink)} /* darkens like a stall's "Step in" */
.nav>.chat-btn{margin:0 6px}
.chat-link{display:inline-flex;align-items:center;gap:6px;--bubble-dot:var(--paper)}
.chat-link .bubble{width:18px;height:18px;color:var(--brass)}
/* shown once the chat widget is on the page (shop.js sets html.poppy) */
html:not(.poppy) [data-poppy]{visibility:hidden}
/* in the footer's Help column it takes no room either, so its links stay evenly spaced where the chat isn't loaded; it comes in far below the first screen, so nothing in sight moves */
html:not(.poppy) .foot [data-poppy]{display:none}
/* on the footer's night the bubble is the header's lamp yellow, its dots the night (the board's note #60) */
.foot .chat-link{--bubble-dot:var(--ink)}
.foot .chat-link .bubble{color:var(--lamp)}
/* On a phone the logo's row carries the desktop's ways too (the board, call #88: a half-empty row reads as "not a real
   shop"): About us, the chat as its bubble (its words from 560 px) and the basket, the logo where it is. Only under
   360 px, where they don't fit beside the logo, About us waits in the footer and the chat is a pill in the corner. */
@media (max-width:699px){
  /* the logo at 4/3, so the row still holds them all at 360 px (2x wraps it under 400 and crowds it above); on a 3x
     phone screen each of its pixels is 4 x 4 screen pixels, still square */
  .logo img{width:132px;height:auto}
  .shopbar,.searchbar{padding-right:6px;column-gap:4px}
  .nav>a:not(.basket-btn):not(.chat-btn){padding:0 5px}
  .nav>.chat-btn{margin:0 2px;padding:0 11px}
  .basket-btn{min-width:46px}
  .foot{padding-bottom:calc(26px + var(--chat-room,0px))}
}
/* on a screen of one pixel per CSS pixel 4/3 would smear its letters: there it's drawn at a
   whole 2x where the row has room for it, and 1x on the narrowest windows */
@media (max-width:699px) and (max-resolution:1.49dppx){.logo img{width:198px;height:32px}}
@media (max-width:479px) and (max-resolution:1.49dppx){.logo img{width:99px;height:16px}}
@media (max-width:559px){.nav>.chat-btn span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}}
@media (max-width:359px){
  .nav>a:not(.basket-btn):not(.chat-btn){display:none}
  .nav>.chat-btn{position:fixed;right:12px;bottom:calc(12px + env(safe-area-inset-bottom));z-index:40;margin:0;padding:0 16px 0 12px;
    box-shadow:0 0 0 2px var(--paper),0 4px 14px rgba(42,35,82,.28)} /* a paper ring keeps it in sight over the night cards and the footer (the board's note #77) */
  .nav>.chat-btn span{position:static;width:auto;height:auto;clip-path:none}
  :root{--chat-room:72px}
}
.thing{padding-top:var(--space-m);padding-bottom:var(--section)}
/* on a phone a page starts close under the ways in, the same small gap on every page: the pills' own 12 px
   under them, then the crumbs or the heading */
@media (max-width:699px){.ways{padding-bottom:var(--space-s)}.crumbs{margin:var(--space-xs) 0 var(--space-m)}.thing{padding-top:0}.wrap.narrow{padding-top:var(--space-xs)}}
.thing-in{display:grid;gap:var(--space-l)}
/* the pictures' own 4:3, so nothing is cut off: their "mockup, not a photo" sits in a bottom corner; a short window
   narrows the picture rather than cropping it */
.thing-pic{position:relative;margin:0;border-radius:16px;overflow:hidden;background:var(--tint);aspect-ratio:4/3;
  max-width:calc(min(560px,70vh)*4/3);width:100%}
.thing-pic img{width:100%;height:100%;object-fit:cover}
/* its versions turn as on its card, and the small picture of the one showing wears a ring (ring1–3, in step with the
   pictures); a picked one stops the turning on it, with a short fade */
.thing-pic .badge{z-index:3}
.thing-picks{display:flex;gap:10px;margin-top:10px}
/* square, and a little smaller on a narrow phone where a thing has many, never under a fingertip's 44 px */
.thing-picks label{position:relative;display:block;flex:0 1 64px;min-width:44px;aspect-ratio:1;border-radius:10px;cursor:pointer}
.thing-picks span{display:block;height:100%;border-radius:10px;overflow:hidden;background:var(--tint)}
.thing-picks img{width:100%;height:100%;object-fit:cover;transform:scale(1.5)}
.thing-picks input{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.thing-picks label::after{content:'';position:absolute;inset:-4px;border:2px solid var(--night);border-radius:13px;opacity:0;
  animation:18s linear 0s infinite both}
.thing-picks label:nth-child(1)::after{animation-name:ring1}.thing-picks label:nth-child(2)::after{animation-name:ring2}.thing-picks label:nth-child(3)::after{animation-name:ring3}
.thing-picks label:has(:focus-visible){outline:3px solid var(--focus);outline-offset:4px}
.thing-pics:has(:checked) .thing-pic .ver,.thing-pics:has(:checked) .thing-picks label::after{animation:none;opacity:0;transition:opacity .3s}
.thing-pics:has([value="1"]:checked) .ver1,.thing-pics:has([value="2"]:checked) .ver2,
.thing-pics:has([value="3"]:checked) .ver3,.thing-pics:has([value="home"]:checked) .verhome,
.thing-pics .thing-picks label:has(:checked)::after{opacity:1}
@media (prefers-reduced-motion:reduce){.thing-picks label:first-child::after{opacity:1}}
/* a photo of our test print stands first and still, its small picture ringed, until another is picked */
.photo-first .thing-pic .ver,.photo-first .thing-picks label::after{animation:none}
.photo-first:not(:has(:checked)) .thing-picks label:first-child::after{opacity:1}
.thing-pics:has([value="photo2"]:checked) .verphoto2,.thing-pics:has([value="photo3"]:checked) .verphoto3{opacity:1}
/* a real photo shows whole, as the board approved it, on the stall's tint; its marker sits just under it, as quiet
   as the mockups' own tag, a few words linking to how we make our photos, only while a photo shows (its line kept, so
   nothing moves) */
.thing-pic img.photo{object-fit:contain}
.photo-mark{display:inline-block;margin-top:6px;color:var(--muted);font-size:14px;line-height:20px;
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
.photo-mark:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.thing-pics:has(.thing-picks :checked:not([value^="photo"])) .photo-mark{visibility:hidden}
.thing-pics:has([value="film"]:checked) .thing-pic .badge{opacity:0}
/* the picture large (zoom.js): a tap on it, or the magnifier in its corner, opens a dialog over the page, the picture
   as big as the screen allows; a tap on it shows its own full size to look around in */
.thing-pic:has(.zoom-open){cursor:zoom-in}
.zoom-open{position:absolute;right:10px;top:10px;z-index:3;display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;
  background:rgba(255,250,240,.92);color:var(--night);box-shadow:0 2px 0 rgba(29,26,47,.25);cursor:zoom-in}
.zoom-open:hover{background:var(--paper)}
.zoom-open:focus-visible,.zoombox button:focus-visible{outline:3px solid var(--focus);outline-offset:3px}
.thing-pics:has([value="film"]:checked) .zoom-open{display:none}
.zoombox{width:100vw;height:100dvh;max-width:none;max-height:none;margin:0;padding:0;border:0;background:rgba(29,26,47,.97);color:var(--paper);overflow:hidden}
.zoombox::backdrop{background:rgba(29,26,47,.5)}
:root:has(.zoombox[open]){overflow:hidden}
.zoombox[open]{animation:zoombox .22s ease-out}
@keyframes zoombox{from{opacity:0}}
.zoom-stage{position:absolute;inset:0;display:grid;place-items:center;padding:56px 12px;overflow:hidden;touch-action:pan-y pinch-zoom;user-select:none}
.zoom-img{display:block;max-width:min(100%,1600px);max-height:calc(100dvh - 112px);width:auto;height:auto;border-radius:10px;background:var(--paper);cursor:zoom-in}
/* a real photo's marker, just under it */
.zoom-stage{align-content:center;gap:8px}
.zoom-mark{color:var(--paper);font-size:15px;line-height:20px;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
.zoom-mark:focus-visible{outline:3px solid var(--focus);outline-offset:3px}
.zoom-stage:has(.zoom-mark:not([hidden])) .zoom-img{max-height:calc(100dvh - 140px)}
.zoom-stage.full{display:block;place-items:start;padding:0;overflow:auto;touch-action:auto}
.zoom-stage.full .zoom-img{max-width:none;max-height:none;width:1600px;border-radius:0;cursor:zoom-out}
.zoombox button{position:absolute;z-index:1;display:grid;place-items:center;width:48px;height:48px;padding:0;border:0;border-radius:50%;
  background:var(--paper);color:var(--night);font:700 30px/1 var(--sans);box-shadow:0 3px 0 rgba(0,0,0,.3);cursor:pointer}
.zoom-x{right:12px;top:max(12px,env(safe-area-inset-top))}
.zoom-closer{right:72px;top:max(12px,env(safe-area-inset-top))}
.zoom-closer[aria-pressed="true"]{background:var(--gold-lt)}
/* the arrows and the count sit on the stage but stay on the screen when the picture is at full size and scrolls */
.zoom-nav{display:contents}
.zoombox .zoom-step{position:fixed;top:calc(50% - 24px)}
.zoom-prev{left:12px}
.zoom-next{right:12px}
.zoom-count{position:fixed;left:0;right:0;bottom:max(14px,env(safe-area-inset-bottom));margin:0;text-align:center;font-size:15px;font-weight:700;pointer-events:none}
/* on a phone the arrows go right under the picture, its count between them, so they never cover it; at full size they
   wait at the screen's bottom */
@media (max-width:699px){
  .zoom-stage:not(.full){display:flex;flex-direction:column;justify-content:center;align-items:center;gap:8px;padding-bottom:max(12px,env(safe-area-inset-bottom))}
  .zoom-img{max-height:calc(100dvh - 124px)}
  .zoom-stage:has(.zoom-mark:not([hidden])) .zoom-img{max-height:calc(100dvh - 152px)}
  .zoom-nav{display:flex;align-items:center;justify-content:center;gap:16px}
  .zoombox .zoom-step,.zoom-count{position:static}
  .zoom-count{min-width:5em}
  .zoom-stage.full .zoom-nav{position:fixed;left:0;right:0;bottom:max(4px,env(safe-area-inset-bottom));padding:0 12px;justify-content:space-between}
}
/* its film: over the picture while its small picture is picked, which plays it (shop.js); that
   small picture wears a play button */
.thing-pic .film{position:absolute;inset:0;z-index:4;width:100%;height:100%;object-fit:contain;background:var(--night);visibility:hidden}
.thing-pics:has([value="film"]:checked) .film{visibility:visible}
.thing-picks .film-pick span::before{content:'';position:absolute;left:50%;top:50%;z-index:1;width:30px;height:30px;margin:-15px 0 0 -15px;border-radius:50%;background:rgba(20,17,31,.72)}
.thing-picks .film-pick span::after{content:'';position:absolute;left:50%;top:50%;z-index:1;margin:-7px 0 0 -4px;border-style:solid;border-width:7px 0 7px 12px;border-color:transparent transparent transparent #fff}
@media (min-width:900px){.thing-picks label{flex-basis:76px}}
.thing-buy{min-width:0}
/* "From the [emblem] Inkbath stall": the words plain, the stall's name bold */
.thing-buy .pshop{display:block;margin:0 0 4px;font-size:15px;font-weight:400;color:var(--muted)}
.thing-buy .pshop .stall-mark{vertical-align:-1px}
.thing-buy .price{font-size:24px}
.thing-buy .btn.main{margin:var(--space-m) 0 var(--space-xs)}
.packs{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.packs li{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid var(--line);font-size:16px}
.packs .price{font-size:17px;margin:0}
.packs .offer-note{display:block;font-size:14px;color:var(--sale)}
.thing-about{max-width:720px;margin-top:var(--space-2xl)}
.thing-about h2{font-size:22px}
.goes{margin-top:var(--space-xl)}
/* the buy bar (views.js buyBar): the button held at the bottom of the screen once the page's
   own has scrolled away above, slid up from under the edge, never over the first screen or the footer: the stall's
   brand over the thing's name and price (on a phone just the price), in the button's height */
.buybar{position:fixed;left:0;right:0;bottom:0;z-index:45;padding:10px var(--edge) calc(10px + env(safe-area-inset-bottom));
  background:var(--paper);box-shadow:0 -2px 0 var(--line),0 -6px 18px rgba(42,35,82,.1);transform:translateY(110%);visibility:hidden;
  transition:transform .25s ease-in,visibility 0s .25s}
.buybar.on{transform:none;visibility:visible;transition:transform .25s ease-out}
@media (prefers-reduced-motion:reduce){.buybar,.buybar.on{transition:none}}
.buybar-in{display:flex;align-items:center;justify-content:space-between;gap:var(--space-s)}
.buybar-what{display:flex;flex-direction:column;min-width:0}
.buybar-what .pshop{line-height:1.3}
.buybar-line{display:flex;align-items:baseline;gap:var(--space-s);min-width:0}
.buybar-line>b{font-size:16px;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.buybar .price{margin:0;font-size:17px;line-height:1.25;white-space:nowrap}
.buybar .btn{flex:none;min-height:44px;padding:10px 18px}
html.buybar-on{scroll-padding-bottom:calc(84px + env(safe-area-inset-bottom))}
@media (max-width:599px){.buybar-line{flex-direction:column;align-items:flex-start;gap:0}.buybar-line>b{display:none}}
@media (max-width:359px){html.buybar-on .nav>.chat-btn{bottom:calc(76px + env(safe-area-inset-bottom))}}
@media (min-width:700px){
  .thing-in{grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:start;gap:var(--space-2xl)}
}
/* the delivery time in the buy box, per country (the board's note #39) */
.deliver{display:grid;grid-template-columns:56px 1fr;gap:12px;margin:var(--space-m) 0 0;padding:14px;border-radius:14px;background:#fff;box-shadow:0 0 0 1px var(--line)}
.deliver-box svg{display:block;width:56px;height:40px}
.deliver h2{margin:2px 0 6px;font-size:17px}
/* a country and its days as one table: the days in their own column, never split, the country wrapping beside them
   when the box is narrow (the board's note #72) */
.deliver ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 12px}
.deliver li{display:grid;grid-column:1/-1;grid-template-columns:subgrid;align-items:baseline;font-size:16px;line-height:1.4}
.deliver li b{white-space:nowrap}
.deliver p{margin:8px 0 0;font-size:14px;line-height:1.45;color:var(--muted)}
/* the parcel only where the box has room for it: not on a phone, nor in a tablet's half-width buy box */
@media (max-width:479px),(min-width:700px) and (max-width:1099px){.deliver{grid-template-columns:1fr}.deliver-box{display:none}}
/* the way on to every gift, where a list ends (the board's note #42) */
.all-link{margin:var(--space-xl) 0 0;font-size:17px;font-weight:700}
.all-link a{color:var(--night)}
/* the footer's pages (Help and contact, the legal pages: src/docs.ts) at reading width, their words as their files have
   them, styled as legal/legal.css styles the files on their own */
.doc{padding-block:var(--space-xl) var(--space-2xl)}
.doc .kicker{color:var(--brass);font-weight:700;font-size:14px;letter-spacing:.06em;text-transform:uppercase;margin:0 0 var(--space-xs)}
.doc h2{font-size:22px;line-height:1.3;margin:var(--space-xl) 0 var(--space-xs)}
.doc h3{font-size:17px;margin:var(--space-m) 0 4px}
.doc p,.doc li{margin:0 0 var(--space-s);overflow-wrap:break-word}
.doc ul,.doc ol{padding-left:1.2em;margin:0 0 var(--space-s)}
.doc .lede{font-size:18px;line-height:1.5}
.doc .updated{font-size:14px;color:var(--muted)}
.doc dl{display:grid;grid-template-columns:max-content 1fr;gap:6px var(--space-m);margin:0 0 var(--space-m)}
.doc dt{color:var(--muted)}
.doc dd{margin:0;min-width:0;overflow-wrap:anywhere}
/* the shop isn't open yet: a calm note, not a warning */
.doc .soon{background:var(--paper2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:15px;margin-bottom:var(--space-m)}
.doc.notice img{width:100%;height:auto;border:1px solid var(--line);background:#fff}
.doc .pick a{display:inline-block;margin:0 10px 4px 0}
.doc .pick a[aria-current]{color:var(--night);font-weight:700;text-decoration:none}
/* the blog: its posts as a list, each beside a square from its cover's middle, and a post at reading width with its
   pictures in a column beside the words; every picture at 2, centred in its frame, so every pixel
   stays whole */
.wrap.blog,.wrap.post{max-width:calc(1000px + 2 * var(--gutter))}
.posts{list-style:none;margin:var(--space-l) 0 0;padding:0}
.post-item{display:grid;grid-template-columns:200px minmax(0,1fr);gap:var(--space-l);align-items:center;padding:var(--space-l) 0;border-top:2px solid var(--line)}
.post-item h2{font-size:22px;margin:4px 0 var(--space-xs)}
.post-item h2 a{color:var(--night);text-decoration:none}
.post-item h2 a:hover{text-decoration:underline}
.post-item p{margin:0}
.post-date{font-size:15px;color:var(--muted);margin:0}
.post-thumb,.post-pic{position:relative;display:block;overflow:hidden;border-radius:24px;background:var(--paper2)}
.post-thumb{height:200px;border-radius:16px}
.post-thumb.night,.post-pic.night{background:linear-gradient(#1d1a3f,#2a2352 55%,#3b3372)}
.post-thumb img,.post-pic img{position:absolute;left:50%;top:50%;max-width:none}
.post>*{max-width:720px}
.post h1{margin:4px 0 var(--space-l)}
.post-pic{height:320px;margin:0 0 var(--space-xl)}
.post-body{font-size:18px}
.post-body h2{font-size:24px;margin:var(--space-xl) 0 var(--space-s)}
.post-body .aside{float:right;clear:right;margin:4px 0 var(--space-s) var(--space-m)}
.post-body p{margin:0 0 var(--space-m)}
.post-body ul{margin:0 0 var(--space-m);padding-left:1.2em}
.post-body li{margin:0 0 var(--space-xs)}
.post-body .portrait{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--space-m);align-items:start;margin:0 0 var(--space-l)}
.post-body .portrait img{display:block;box-sizing:content-box;padding:12px 16px 0;background:var(--paper2);border-radius:16px}
.post-body .portrait p{margin:0}
.post-body .portrait .who{font-size:16px;color:var(--muted);margin:2px 0 var(--space-xs)}
.post-body .portrait .who b{font-size:20px;color:var(--night)}
.post-by{color:var(--muted);font-style:italic;margin:var(--space-xl) 0 0}
.post .sub{margin-top:var(--space-2xl)}
/* wide enough: the pictures stand in the column right of the words, each beside the paragraph after it */
@media (min-width:1080px){.post-body .aside{width:240px;margin:6px -280px var(--space-m) 40px}}
@media (max-width:1079px){.post-body h2{clear:both}}
@media (max-width:699px){
  .post-item{grid-template-columns:minmax(0,1fr);gap:var(--space-s)}
  .post-thumb{height:140px}
  .post-pic{height:240px}
  .post-body .aside{float:none;margin:0 0 var(--space-m)}
  .post-body .aside img{margin:0 auto}
  /* a portrait: who beside it, what they say under both */
  .post-body .portrait{align-items:center;row-gap:var(--space-s)}
  .post-body .portrait figcaption{display:contents}
  .post-body .portrait p:not(.who){grid-column:1/-1}
}
