/* Luxury Notes storefront.

   The conventional store layout on purpose: a photo-led grid, a product page with a
   variant picker, a cart drawer. People already know how to use this shape, and a
   fragrance shop is not the place to teach anyone a new one.

   Everything is sized in one scale and spaced with gap rather than per-element margins,
   so a row of cards keeps its baselines whatever it holds. */

:root{
  /* Neutrals carry a little warmth rather than sitting on pure grey — a shop selling
     something you put on your skin should not read like a spreadsheet. */
  --bg:#fffefc; --surface:#f6f5f2; --sunk:#efeeea;
  --line:#e7e4de; --line-2:#d8d4cc; --line-soft:#f0eeea;
  --ink:#23282c; --ink-2:#4a5359; --muted:#6d757b; --faint:#9aa0a4;
  --slate:#2f3c48; --slate-hi:#3f5160;
  --gold:#a8862f; --low:#a8503a;

  /* One scale, used by size of thing: controls, then panels, then the big surfaces.
     Corners this soft are most of the difference between a grid of boxes and a page. */
  --r-sm:10px; --r:14px; --r-lg:18px;
  /* Depth instead of an outline, for the few things that genuinely sit above the page. */
  --lift:0 1px 2px rgba(35,40,44,.04), 0 6px 18px rgba(35,40,44,.05);
  --sans:"IBM Plex Sans Arabic",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --tap:44px;
}
*{box-sizing:border-box}
/* hidden means hidden. Any display: rule on a class otherwise outranks the browser's own, and
   a badge or chip that should be gone shows as an empty shape. */
[hidden]{display:none!important}
html,body{margin:0;padding:0}
/* The page is a column that is at least as tall as the window, with the main content
   allowed to grow. Without this a short page — a one-line cart, an order confirmation —
   leaves the footer floating halfway up with blank space beneath it. dvh rather than vh
   so a phone's collapsing address bar does not leave a gap either. */
body{background:var(--bg);color:var(--ink);font-family:var(--sans);
  font-size:15px;line-height:1.55;-webkit-font-smoothing:antialiased;
  min-height:100vh;min-height:100dvh;display:flex;flex-direction:column}
/* Nothing on any page should butt against the footer. The review form exposed it —
   its Send button sat directly on the footer's edge — but every page had the same
   gap missing, so it is fixed once here rather than on the section that showed it. */
main{flex:1 0 auto;padding-bottom:56px}
footer{margin-top:auto}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;cursor:pointer}
.wrap{max-width:1180px;margin:0 auto;padding:0 20px}
/* The size strip is a flex item of <body> rather than a block inside <header>, and a
   flex item is free to grow past its container to fit its contents. This one holds a
   horizontally scrolling row, so without a definite width it stretched the whole page
   a pixel or two sideways instead of scrolling inside itself. */
.subbar{width:100%;min-width:0}
.num{unicode-bidi:isolate}

.ann{background:var(--slate);color:#fff;text-align:center;font-size:12.5px;padding:8px 16px}

header{position:sticky;top:0;z-index:40;background:var(--bg);border-bottom:1px solid var(--line)}
.hbar{display:flex;align-items:center;gap:18px;min-height:78px}
/* The mark sits above the words, so sizing it to a short bar makes the words too small
   to read. The bar is given the height the logo needs instead of the other way round. */
.brand{display:flex;align-items:center;flex:none}
.brand img{height:52px;width:auto;object-fit:contain;display:block}
@media (max-width:560px){ .brand img{height:40px} }
.search{flex:1;min-width:0}
.search input{width:100%;height:40px;border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);padding:0 12px;font:inherit;font-size:14px;color:var(--ink)}
.search input:focus{outline:2px solid var(--slate);outline-offset:-1px;background:var(--bg)}
.hacts{display:flex;align-items:center;gap:4px}
.icon{height:var(--tap);min-width:var(--tap);border:0;background:none;display:grid;
  place-items:center;border-radius:var(--r-sm);position:relative}
.icon:hover{background:var(--surface)}
.icon:focus-visible{outline:2px solid var(--slate);outline-offset:-2px}
.count{position:absolute;top:5px;inset-inline-end:5px;background:var(--slate);color:#fff;
  font-size:10.5px;line-height:1;min-width:17px;height:17px;border-radius:9px;
  display:grid;place-items:center;padding:0 4px;font-variant-numeric:tabular-nums}
.lang{display:flex;border:1px solid var(--line-2);border-radius:100px;overflow:hidden}
.lang a{font-size:12px;padding:7px 11px;line-height:1;color:var(--muted)}
.lang a.on{background:var(--slate);color:#fff}

.chips{display:flex;gap:8px;overflow-x:auto;padding:14px 0;border-bottom:1px solid var(--line);
  scrollbar-width:none}
.chips::-webkit-scrollbar{display:none}
.chip{border:1px solid var(--line-2);background:var(--bg);border-radius:100px;
  padding:7px 15px;font-size:13.5px;white-space:nowrap;color:var(--ink-2)}
.chip.on{background:var(--slate);border-color:var(--slate);color:#fff}
.chip:focus-visible{outline:2px solid var(--slate);outline-offset:2px}

.tools{display:flex;align-items:baseline;justify-content:space-between;padding:22px 0 14px;gap:12px}
.tools h1{font-size:20px;font-weight:600;margin:0}
.tools span{font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));
  gap:34px 24px;padding-bottom:64px}
.card{display:flex;flex-direction:column;gap:9px}
.shot{aspect-ratio:1;background:var(--surface);border-radius:var(--r);
  overflow:hidden;position:relative;display:grid;place-items:center;
  transition:transform .28s cubic-bezier(.2,.7,.3,1), box-shadow .28s ease}
/* The picture grows inside its tile rather than the tile growing on the page: the grid
   stays still, and only the thing under the cursor moves. */
.shot img{transition:transform .45s cubic-bezier(.2,.7,.3,1)}
/* contain, not cover: the tile is square on a computer and 4:3 or narrower elsewhere, and
   cover filled it by cutting the cap or the base off a tall bottle. Photographs are framed
   on this tile's own colour when uploaded (ImageStore), so the letterbox left by contain is
   invisible. */
.shot img{width:100%;height:100%;object-fit:contain}
.ph{width:44%;color:var(--faint);opacity:.4}
.tag{position:absolute;top:10px;inset-inline-start:10px;background:var(--bg);
  font-size:10.5px;padding:4px 9px;border-radius:100px;color:var(--low);
  box-shadow:var(--lift)}
.card:hover .shot,.card:focus-visible .shot{transform:translateY(-4px);box-shadow:var(--lift)}
.card:hover .shot img,.card:focus-visible .shot img{transform:scale(1.06)}
/* A press that answers the finger. Short, and it ends where it started. */
.card:active .shot{transform:translateY(-1px) scale(.985);transition-duration:.1s}
.card .cname,.card .cprice{transition:color .2s ease}
.card:hover .cname{color:var(--slate)}
.card-a:focus-visible{outline:2px solid var(--slate);outline-offset:3px;border-radius:4px}
.chouse{font-size:11px;color:var(--faint);letter-spacing:.07em;text-transform:uppercase}
.cname{font-size:14.5px;font-weight:500;line-height:1.35;margin:0;
  /* Two lines' worth whether the name needs them or not, so the price sits on the same
     line across a row. Fragrance names vary wildly in length and a price that drifts
     down one card in five makes a tidy grid look accidental. */
  min-height:2.7em}
.cprice{font-size:14px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.cprice b{font-weight:600}
.none{grid-column:1/-1;padding:50px 0;text-align:center;color:var(--muted)}
.none strong{display:block;color:var(--ink);font-size:16px;margin-bottom:5px}

/* product page */
.crumb{padding:16px 0 0;font-size:13px;color:var(--muted)}
.pdgrid{display:grid;grid-template-columns:1fr;gap:24px;padding:14px 0 40px}
.gal{background:var(--surface);border-radius:var(--r-lg);
  aspect-ratio:1;display:grid;place-items:center;overflow:hidden}
.gal img{width:100%;height:100%;object-fit:contain}
.gal .ph{width:38%}
.phouse{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
.pname{font-size:26px;font-weight:600;margin:3px 0 10px;line-height:1.22;text-wrap:balance}
.pprice{font-size:23px;font-weight:600;font-variant-numeric:tabular-nums}
.pstock{font-size:13px;color:var(--muted);margin-top:3px}
.pstock.low{color:var(--low)}
.vlabel{font-size:12.5px;font-weight:500;margin:20px 0 8px}
.vars{display:flex;flex-wrap:wrap;gap:8px}
.var{border:1px solid var(--line-2);background:var(--bg);border-radius:var(--r-sm);padding:11px 16px;
  font-size:14px;min-width:72px;text-align:center;font-variant-numeric:tabular-nums}
.var.on{border-color:var(--slate);background:var(--slate);color:#fff}
.var:disabled{opacity:.4;cursor:not-allowed;text-decoration:line-through}
.var:focus-visible{outline:2px solid var(--slate);outline-offset:2px}
.add{width:100%;margin-top:22px;background:var(--slate);color:#fff;border:0;
  border-radius:var(--r-sm);height:52px;font-size:15.5px;font-weight:500;
  transition:background .16s ease}
.add:hover{background:var(--slate-hi)}
.add:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.acc{margin-top:22px;border-top:1px solid var(--line)}
.acc details{border-bottom:1px solid var(--line-soft)}
.acc summary{padding:13px 0;font-size:14px;font-weight:500;cursor:pointer;list-style:none;
  display:flex;justify-content:space-between}
.acc summary::-webkit-details-marker{display:none}
.acc summary::after{content:"+";color:var(--muted)}
.acc details[open] summary::after{content:"−"}
.acc .body{padding:0 0 15px;font-size:14px;color:var(--ink-2)}
.pyr{display:grid;grid-template-columns:86px 1fr;gap:8px 12px;font-size:13.5px;margin:0}
.pyr dt{color:var(--faint)}
.pyr dd{margin:0}

/* cart drawer */
.scrim{position:fixed;inset:0;background:rgba(16,24,28,.44);z-index:50;opacity:0;
  pointer-events:none;transition:opacity .2s}
.scrim.on{opacity:1;pointer-events:auto}
.cart{position:fixed;z-index:60;top:0;bottom:0;inset-inline-end:0;width:min(400px,92vw);
  background:var(--bg);display:flex;flex-direction:column;
  transform:translateX(101%);transition:transform .26s ease;
  visibility:hidden;pointer-events:none}
[dir="rtl"] .cart{transform:translateX(-101%)}
.cart.on{transform:none!important;visibility:visible;pointer-events:auto}
.chead{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;
  border-bottom:1px solid var(--line)}
.chead h2{font-size:16px;font-weight:600;margin:0}
.clines{flex:1;overflow:auto;padding:6px 18px}
.line{display:grid;grid-template-columns:54px 1fr auto;gap:14px;padding:16px 0;
  border-bottom:1px solid var(--line-soft)}
.line .th{aspect-ratio:1;background:var(--surface);
  border-radius:var(--r-sm);overflow:hidden;display:grid;place-items:center}
.line .th .ph{width:50%}
.line .th img{width:100%;height:100%;object-fit:contain}
.lname{font-size:13.5px;font-weight:500;line-height:1.3}
.lsize{font-size:12px;color:var(--muted);margin-top:2px}
.lqty{display:flex;align-items:center;gap:9px;margin-top:6px}
.lqty button{border:1px solid var(--line-2);background:var(--bg);width:26px;height:26px;
  border-radius:3px;line-height:1}
.lqty span{font-size:13px;font-variant-numeric:tabular-nums;min-width:14px;text-align:center}
.lprice{font-size:14px;font-variant-numeric:tabular-nums;text-align:end}
.empty{padding:44px 0;text-align:center;color:var(--muted);font-size:14px}
.cfoot{border-top:1px solid var(--line);padding:16px 18px;display:flex;flex-direction:column;gap:10px}
.srow{display:flex;justify-content:space-between;font-size:14px}
.srow.total{font-size:16px;font-weight:600}
.srow span:last-child{font-variant-numeric:tabular-nums}
.co{background:var(--slate);color:#fff;border:0;border-radius:var(--r-sm);height:50px;
  font-size:15px;font-weight:500}
.co:hover{background:var(--slate-hi)}
.cnote{font-size:12px;color:var(--muted);text-align:center;margin:0}

footer{border-top:1px solid var(--line);background:var(--surface);padding:30px 0 44px;
  font-size:13px;color:var(--muted)}
.fgrid{display:flex;flex-wrap:wrap;gap:26px;justify-content:space-between}
footer b{display:block;color:var(--ink);font-weight:600;font-size:13px;margin-bottom:5px}

@media (min-width:760px){
  .pdgrid{grid-template-columns:1fr 1fr;gap:34px;align-items:start}
}
@media (max-width:560px){
  .grid{grid-template-columns:repeat(2,1fr);gap:22px 14px}
  .pyr{grid-template-columns:76px 1fr}

  /* Anything under 16px makes iOS zoom the page the moment it is focused, and the
     customer then has to pinch back out to see the form they are filling in. It happens
     on every checkout, which makes it the most expensive small number in this file. */
  .search input,.field input,.field textarea,.field select{font-size:16px}
  .search input{height:44px}

  /* The bars above the grid were eating a third of a phone screen before a customer
     saw a single fragrance. */
  .ann{font-size:12px;padding:7px 14px}
  .chips{padding:11px 0}
  .tools{padding:18px 0 10px}
  .pname{font-size:23px}

  /* Room for the home indicator, so the checkout button is not half under it. */
  .cfoot{padding-bottom:calc(16px + env(safe-area-inset-bottom))}
  .wrap{padding:0 16px}
}

/* The grey flash Safari paints over a tapped link says nothing the press animation is not
   already saying, and it lands on the wrong shape. */
a,button{-webkit-tap-highlight-color:transparent}

/* A stuck :hover on a touch screen leaves a card lifted after the finger has gone. */
@media (hover:none){
  .card:hover .shot{transform:none;box-shadow:none}
  .card:hover .shot img{transform:none}
  .card:hover .cname{color:var(--ink)}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}

/* ---- checkout ----------------------------------------------------------------
   One column on a phone, two on a desktop, with the summary beside the form rather
   than below it: a customer filling in an address should be able to see what they
   are paying for without scrolling away from the field they are typing in. */

.co-wrap{padding-bottom:60px}
.co-title{font-size:22px;font-weight:600;margin:24px 0 16px}
.co-err{background:#fbf0ec;color:var(--low);
  padding:13px 16px;border-radius:var(--r);font-size:14px;margin:0 0 18px}

.co-form{display:grid;grid-template-columns:1fr;gap:26px;align-items:start}
.co-sec h2{font-size:15px;font-weight:600;margin:0 0 14px}
.co-sec .co-sum-h{margin-top:26px}

.field{display:flex;flex-direction:column;gap:5px;margin-bottom:14px}
.field label{font-size:13px;color:var(--ink-2);font-weight:500}
.field input,.field textarea,.field select{
  border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--bg);
  padding:12px 14px;font:inherit;font-size:15px;color:var(--ink);width:100%}
.field textarea{resize:vertical;line-height:1.5}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:2px solid var(--slate);outline-offset:-1px}
.field .help{font-size:12px;color:var(--muted)}

.pay{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line);
  border-radius:var(--r);padding:15px 16px;margin-bottom:10px;cursor:pointer;
  transition:border-color .16s ease,background .16s ease}
.pay:has(input:checked){border-color:var(--slate);background:var(--surface)}
.pay input{margin-top:3px;accent-color:var(--slate)}
.pay span{display:flex;flex-direction:column;gap:2px}
.pay b{font-weight:500;font-size:14.5px}

.co-sum{border-radius:var(--r);padding:18px;background:var(--surface)}
.co-sum .srow{padding:4px 0;gap:14px}
.co-sum .srow i{font-style:normal;color:var(--muted);font-size:12.5px}
.co-sum .srow.total{border-top:1px solid var(--line-2);margin-top:7px;padding-top:9px}
.add:disabled{opacity:.5;cursor:not-allowed}

/* ---- order confirmation ---- */
.done{max-width:560px}
.done-ref{display:flex;flex-direction:column;gap:4px;border-radius:var(--r);
  padding:20px;margin:0 0 18px;background:var(--surface)}
.done-ref span{font-size:12.5px;color:var(--muted)}
.done-ref strong{font-size:25px;font-weight:600;letter-spacing:.06em}
.done-body{margin:0 0 22px;color:var(--ink-2)}
.insta{background:var(--surface);border-radius:var(--r);padding:20px}
.insta h2{font-size:15px;font-weight:600;margin:0 0 12px}
.insta-row{display:flex;justify-content:space-between;gap:14px;padding:6px 0;font-size:14px}
.insta-row strong{font-weight:600;font-variant-numeric:tabular-nums}
.insta .help{display:block;font-size:12.5px;color:var(--muted);margin:9px 0 0}
.insta-go{display:grid;place-items:center;text-decoration:none;margin-top:14px}
.done-back{display:inline-block;margin-top:22px;font-size:14px;color:var(--muted);
  text-decoration:underline}

@media (min-width:820px){
  .co-form{grid-template-columns:1.25fr 1fr;gap:40px}
}

/* ---- tracking an order --------------------------------------------------------
   A narrow column: this page is read, not browsed, and it is usually opened on a
   phone from a message with the reference in it. */

.track{max-width:560px}
.track-form{background:var(--surface);border-radius:var(--r);padding:20px;margin-bottom:24px}
.track-intro{margin:0 0 14px}
.track-form .add{margin-top:6px}

.found{background:var(--surface);border-radius:var(--r);padding:20px;margin-bottom:22px}
.found-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding-bottom:12px;margin-bottom:6px;border-bottom:1px solid var(--line)}
.found-head strong{font-size:21px;font-weight:600;letter-spacing:.06em}
.found-items-h{margin:12px 0 4px}
.found .srow{padding:4px 0}
.found .srow i{font-style:normal;color:var(--muted);font-size:12.5px}
.found .srow.total{border-top:1px solid var(--line-2);margin-top:8px;padding-top:9px;
  font-weight:600;font-size:15.5px}

/* Status as a shape as well as a word, so the state reads before the sentence does. */
.pill{font-size:12px;padding:4px 10px;border-radius:100px;white-space:nowrap;
  border:1px solid var(--line-2);background:var(--surface);color:var(--ink-2)}
.pill-confirmed{background:#eaf4ef;border-color:#bcdcca;color:#215c41}
.pill-cancelled{background:#fdf1ef;border-color:#e8c4bb;color:var(--low)}

.others h2{font-size:15px;font-weight:600;margin:0 0 10px}
.other-row{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center;
  padding:14px 0;border-bottom:1px solid var(--line-soft)}
.other-row:last-child{border-bottom:0}
.other-ref{display:flex;flex-direction:column;gap:1px;min-width:0}
.other-ref strong{font-weight:600;letter-spacing:.04em}
.other-total{font-variant-numeric:tabular-nums;font-size:14px}

.foot-link{text-decoration:underline;color:var(--muted)}

@media (max-width:480px){
  .other-row{grid-template-columns:1fr auto}
  .other-total{grid-column:2}
  .other-row .pill{grid-column:1/-1;justify-self:start}
}

.scent-desc{margin:12px 0 0;font-size:14px;line-height:1.6;color:var(--ink-2)}


/* The selected payment reads as chosen rather than merely outlined. */
.pay:has(input:checked){border-color:var(--slate);background:var(--sunk)}

/* ---- account ---- */
.sent{background:var(--surface);border-radius:var(--r);padding:18px 20px;margin:0 0 18px;
  font-size:14.5px;color:var(--ink-2)}
.acct-who{font-size:15px;font-weight:600;word-break:break-all}
.acct-addr{text-align:end;color:var(--muted);font-size:13.5px;max-width:60%}
.pill-btn{border:1px solid var(--line-2);background:var(--bg);border-radius:100px;
  padding:7px 15px;font-size:13px;color:var(--ink-2);white-space:nowrap}
.pill-btn:hover{border-color:var(--slate);color:var(--ink)}

/* ---- how many ---- */
.qty-row{display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin-top:20px}
.qty-label{margin:0}
.qty{display:flex;align-items:center;gap:2px;border:1px solid var(--line-2);
  border-radius:100px;padding:4px;background:var(--bg)}
.qty button{width:38px;height:38px;border:0;background:none;border-radius:100px;
  font-size:17px;line-height:1;color:var(--ink);display:grid;place-items:center}
.qty button:hover:not(:disabled){background:var(--surface)}
.qty button:disabled{color:var(--faint);cursor:not-allowed}
.qty button:focus-visible{outline:2px solid var(--slate);outline-offset:-2px}
.qty span{min-width:34px;text-align:center;font-size:15.5px;font-variant-numeric:tabular-nums}

/* ---- search suggestions ---- */
.search{position:relative}
.suggest{position:absolute;top:calc(100% + 6px);inset-inline:0;z-index:60;
  background:var(--bg);border-radius:var(--r);box-shadow:var(--lift);
  border:1px solid var(--line);overflow:hidden;max-height:60vh;overflow-y:auto}
.sg{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:12px 16px;text-decoration:none;border-bottom:1px solid var(--line-soft)}
.sg:last-child{border-bottom:0}
.sg:hover,.sg.on{background:var(--surface)}
.sg-label{font-size:14.5px;color:var(--ink)}
.sg-sub{font-size:11.5px;color:var(--faint);letter-spacing:.06em;text-transform:uppercase;
  white-space:nowrap}


/* ---- movement -----------------------------------------------------------------
   Only where something actually changed. Controls answer a tap, the drawer and the
   suggestions arrive from where they belong, and nothing fades in merely because the
   page loaded — a shop that animates itself on every scroll is a shop that feels slow. */

.add,.co,.var,.chip,.pill-btn,.qty button{
  transition:background .16s ease,border-color .16s ease,color .16s ease,transform .12s ease}
.add:active,.co:active{transform:scale(.99)}
.var:active,.chip:active,.qty button:active:not(:disabled){transform:scale(.96)}

/* The gallery cross-fades when the size changes, so the new vial reads as a change of
   picture rather than a flicker. */
.gal img{transition:opacity .2s ease}
.gal img.swapping{opacity:.35}

/* The drawer's contents arrive just after the drawer itself. */
.cart.on .clines,.cart.on .cfoot{animation:rise .28s cubic-bezier(.2,.7,.3,1) both}
.cart.on .cfoot{animation-delay:.04s}
@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

.suggest{animation:drop .16s ease both}
@keyframes drop{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){
  .shot,.shot img,.gal img,.card:active .shot{transition:none!important;transform:none!important}
  .cart.on .clines,.cart.on .cfoot,.suggest{animation:none!important}
}

/* ---- the PerfumeIQ panel ----
   Sits inside the notes section under the pyramid the tracker supplies. Set apart by rules
   and spacing rather than boxes, so it reads as more of the same section. */
.piq{margin-top:16px;padding-top:16px;border-top:1px solid var(--line-soft)}
.piq-head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.piq-score{font-size:30px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.piq-head-r{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.piq-stars{color:var(--gold);font-size:14px;letter-spacing:.06em}
.piq-votes{font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}
.piq-year{font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}

.piq-sec{margin-bottom:18px}
.piq-sec-t{display:block;font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--faint);margin-bottom:10px}

.piq-row{display:grid;grid-template-columns:86px 1fr;gap:10px;align-items:start;
  margin-bottom:8px}
.piq-row-l{font-size:11.5px;color:var(--faint);padding-top:5px}
.piq-chips{display:flex;flex-wrap:wrap;gap:6px}
.piq-chip{background:var(--surface);border-radius:100px;padding:5px 11px 5px 8px;
  font-size:12.5px;color:var(--ink-2);display:inline-flex;align-items:center;gap:6px}
.piq-note-i{width:15px;height:15px;flex:none;opacity:.92}
[dir="rtl"] .piq-chip{padding:5px 8px 5px 11px}

.piq-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}
.piq-card{display:flex;flex-direction:column;gap:5px;background:var(--surface);
  border-radius:var(--r-sm);padding:12px 14px}
.piq-card-t{font-size:11.5px;color:var(--faint)}
.piq-card-n{font-size:19px;font-weight:600;font-variant-numeric:tabular-nums;line-height:1}
.piq-card-n i{font-style:normal;font-size:12px;font-weight:400;color:var(--faint)}
.piq-card-d{font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums}

.piq-bar{display:flex;flex-direction:column;gap:5px}
.piq-bar-l{font-size:12.5px;color:var(--ink-2)}
.piq-bar-p{font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.piq-track{display:block;height:6px;border-radius:3px;background:var(--sunk);overflow:hidden}
.piq-track b{display:block;height:100%;border-radius:3px;background:var(--slate);
  transition:width .6s cubic-bezier(.2,.7,.3,1)}

.piq-foot{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);
  padding-top:12px;border-top:1px solid var(--line-soft)}

@media (max-width:560px){
  .piq-grid{grid-template-columns:1fr}
  .piq-row{grid-template-columns:64px 1fr}
}

/* the identity bar and the season / occasion marks */
.piq-bar-id{display:flex;align-items:center;gap:9px;margin-bottom:16px}
.piq-dot{width:26px;height:26px;border-radius:100px;background:var(--slate);color:#fff;
  font-size:10px;font-weight:700;letter-spacing:.04em;display:grid;place-items:center;flex:none}
.piq-id-t{font-size:12.5px;color:var(--ink-2)}
.piq-bar-h{display:flex;align-items:center;gap:7px}
.piq-ico{font-size:13px;line-height:1;flex:none}
.piq-bar-h .piq-bar-l{flex:1;min-width:0}

/* Tap targets, kept at the end of the file on purpose.

   An earlier attempt put these beside the rest of the phone layout, a hundred lines
   above where .qty and .icon are defined. Same specificity, later wins: the stepper
   went back to 38px and nobody could see it in a desktop browser. A phone measured it
   at 38 and 34. So they live here, after everything they override.

   A finger pad is about nine millimetres — 44px is the floor, and line-height alone
   does not reach it, so each one gets a real min-height. */
@media (max-width:560px){
  .chip{padding:11px 17px;font-size:14px;min-height:44px;display:inline-flex;
    align-items:center}
  .lang a{padding:11px 14px;min-height:44px;display:flex;align-items:center}
  .var{padding:13px 18px;min-height:44px}
  .qty button{width:44px;height:44px}
  .icon{min-width:44px;min-height:44px;display:grid;place-items:center}

  /* The strip of sizes runs past the edge of the screen. It scrolls, but nothing said
     so — the last chip was simply cut in half. A fade at the trailing edge says it. */
  .chips{-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;
    mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent)}
  [dir="rtl"] .chips{mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent)}
  .chips .chip{scroll-snap-align:start}

  /* "Dries down to" is three words in a 64px column. Give the label its own line. */
  .piq-row{grid-template-columns:1fr;gap:6px}
  .piq-row-l{padding-top:0}
}

/* ---- the header on a phone -----------------------------------------------------

   It used to be three stacked bands — announcement, logo row, then a search field on
   its own line because it could not fit beside anything — and the whole lot was stuck
   to the top of the screen. On a 402px phone that is a third of the display spent
   before the first bottle, on every scroll of every page.

   So the field folds behind a button, the way it does in every shop app, and the bar
   is one row: mark on the left, search and language and bag on the right. Tapping the
   button drops the field under the bar, full width, and focuses it. */
.searchbtn{display:none}

@media (max-width:560px){
  .searchbtn{display:grid}

  /* Dead centre, whatever sits on either side. Sharing the bar out in columns puts the
     mark in the middle of the leftovers, not the middle of the screen, and the two
     controls on the right outweigh the one on the left by exactly enough to see. */
  .hbar{position:relative}
  .brand{position:absolute;left:50%;transform:translateX(-50%)}

  /* Three columns rather than a row, so the mark sits in the middle of the bar instead
     of against the left edge with the rest of the width empty beside it. The outer
     columns are equal, so the mark is centred on the bar and not merely on what is left
     over; start and end flip with the writing direction on their own. */
  /* .hbar is the .wrap element, so its padding replaces the page's side padding rather
     than adding to it: shorthand it and the search icon ends up against the glass. */
  .hbar{display:flex;justify-content:space-between;align-items:center;
    min-height:0;padding:6px 16px;gap:6px}
  .brand img{height:41px}
  .hacts{gap:0}

  /* The language switch was the loudest thing on the bar — a filled dark pill holding
     both languages, heavier than the mark it sat beside, and it crowded the bag against
     the edge. On a phone it shows only the language you are not reading, as a plain
     glyph: one tap, same result, and the bar goes quiet. */
  .lang{border:0;border-radius:0}
  .lang a.on{display:none}
  .lang a{min-width:44px;min-height:44px;padding:0;display:grid;place-items:center;
    font-size:14px;color:var(--ink-2);background:none}

  /* Out of the bar's flow entirely, so the bar keeps its single row whether the field
     is open or shut. */
  .search{position:absolute;inset-inline:0;top:100%;display:none;
    background:var(--bg);border-bottom:1px solid var(--line);padding:10px 16px;
    box-shadow:0 10px 20px -18px rgb(20 22 26 / .5)}
  .search.open{display:block}
  .search input{height:44px}
  .suggest{inset-inline:16px}

}


/* ---- the catalogue: filters, quick view, saved, looked at ------------------------
   Everything here sits on the grid the server drew. The card is a block rather than one
   link, because a heart and a quick-view button cannot live inside an <a>: the picture
   and the words are each a link, and the two buttons float over the picture. */

:root{--heart:#b5473a}
.card{position:relative}
.card-a{display:flex;flex-direction:column;gap:9px}
.shot-a{display:grid;place-items:center;width:100%;height:100%}
.card[hidden]{display:none}

/* The heart. Outlined until saved, then filled — the state reads without a label. */
.fav{position:absolute;top:10px;inset-inline-end:10px;width:36px;height:36px;border:0;
  border-radius:100px;background:rgb(255 254 252 / .9);display:grid;place-items:center;
  box-shadow:var(--lift);color:var(--ink-2)}
.fav svg{fill:none;stroke:currentColor;stroke-width:1.7;transition:transform .2s ease,fill .2s ease}
.fav:hover{color:var(--heart)}
.fav.on{color:var(--heart)}
.fav.on svg{fill:currentColor;animation:beat .32s cubic-bezier(.2,.7,.3,1)}
.fav:focus-visible{outline:2px solid var(--slate);outline-offset:2px}
@keyframes beat{40%{transform:scale(1.22)}100%{transform:scale(1)}}
.fav-lg{position:static;box-shadow:none;background:var(--surface);width:44px;height:44px;flex:none}
.pname-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.pname-row .pname{margin-inline-end:0}

/* Quick view rises out of the picture on hover. On a touch screen there is no hover, so
   it is a small round button that is always there. */
.qv-btn{position:absolute;inset-inline:12px;bottom:12px;height:40px;border:0;border-radius:100px;
  background:rgb(255 254 252 / .94);box-shadow:var(--lift);display:flex;align-items:center;
  justify-content:center;gap:7px;font-size:13px;font-weight:500;color:var(--ink);
  opacity:0;transform:translateY(6px);transition:opacity .2s ease,transform .2s ease,background .16s ease}
.card:hover .qv-btn,.card:focus-within .qv-btn{opacity:1;transform:none}
.qv-btn:hover{background:var(--slate);color:#fff}
.qv-btn:focus-visible{opacity:1;transform:none;outline:2px solid var(--slate);outline-offset:2px}
@media (hover:none){
  .qv-btn{opacity:1;transform:none;inset-inline:auto;inset-inline-end:10px;bottom:10px;
    width:36px;height:36px;padding:0}
  .qv-btn span{display:none}
}

/* the bar above the grid */
.tools{align-items:center;flex-wrap:wrap}
.tools-l{display:flex;align-items:baseline;gap:12px;min-width:0}
.tools-r{display:flex;align-items:center;gap:8px}
.tool-btn{display:inline-flex;align-items:center;gap:7px;height:40px;padding:0 14px;
  border:1px solid var(--line-2);background:var(--bg);border-radius:100px;font-size:13.5px;color:var(--ink)}
.tool-btn:hover{border-color:var(--slate)}
.tool-btn:focus-visible{outline:2px solid var(--slate);outline-offset:2px}
.tool-n{background:var(--slate);color:#fff;font-size:11px;min-width:19px;height:19px;border-radius:10px;
  display:grid;place-items:center;padding:0 5px}
.sort select{height:40px;border:1px solid var(--line-2);background:var(--bg);border-radius:100px;
  padding:0 34px 0 14px;font:inherit;font-size:13.5px;color:var(--ink);appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236d757b' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center}
[dir="rtl"] .sort select{padding:0 14px 0 34px;background-position:left 14px center}
.sort select:focus-visible{outline:2px solid var(--slate);outline-offset:2px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* what is applied */
.applied{display:flex;flex-wrap:wrap;gap:8px;margin:-2px 0 18px}
.apill{display:inline-flex;align-items:center;gap:8px;border:0;background:var(--sunk);
  border-radius:100px;padding:6px 8px 6px 13px;font-size:13px;color:var(--ink)}
[dir="rtl"] .apill{padding:6px 13px 6px 8px}
.apill span:last-child{width:18px;height:18px;border-radius:100px;display:grid;place-items:center;
  background:var(--bg);color:var(--muted);font-size:13px;line-height:1}
.apill:hover span:last-child{background:var(--slate);color:#fff}
.apill-clear{border:0;background:none;font-size:13px;color:var(--muted);text-decoration:underline;padding:6px 4px}
.none .pill-btn{margin-top:14px}

.chip-saved{display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.chip-saved svg{fill:none;stroke:var(--heart);stroke-width:2}
.chip-saved.on svg{fill:#fff;stroke:#fff}

/* the filter drawer: the cart's twin, from the other side */
.fdrawer{position:fixed;z-index:60;top:0;bottom:0;inset-inline-start:0;width:min(380px,92vw);
  background:var(--bg);display:flex;flex-direction:column;
  transform:translateX(-101%);transition:transform .26s ease;visibility:hidden;pointer-events:none}
[dir="rtl"] .fdrawer{transform:translateX(101%)}
.fdrawer.on{transform:none!important;visibility:visible;pointer-events:auto}
.fbody{flex:1;overflow:auto;padding:4px 18px 18px}
.fsec{padding:18px 0;border-bottom:1px solid var(--line-soft)}
.fsec:last-child{border-bottom:0}
.fsec h3{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);
  font-weight:500;margin:0 0 12px}
.fchips{display:flex;flex-wrap:wrap;gap:8px}
.fchips .chip{cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.fcount{font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.chip.on .fcount{color:rgb(255 255 255 / .75)}
.fhouses{display:flex;flex-direction:column}
.fhouse{display:flex;align-items:center;gap:11px;padding:10px 2px;font-size:14px;cursor:pointer;
  border-bottom:1px solid var(--line-soft)}
.fhouse:last-child{border-bottom:0}
.fhouse input{width:18px;height:18px;accent-color:var(--slate);margin:0;flex:none}
.fhouse span:nth-of-type(1){flex:1}
.fhouse.dim{color:var(--faint)}
.ffoot{border-top:1px solid var(--line);padding:14px 18px calc(14px + env(safe-area-inset-bottom));
  display:flex;gap:10px;align-items:center}
.ffoot .co{flex:1;height:48px}

/* Two range inputs laid over one track. Only the thumbs take the pointer, so either can be
   grabbed wherever the other one sits. */
.range{position:relative;height:30px;--lo:0%;--hi:100%}
.range::before,.range::after{content:"";position:absolute;top:13px;height:4px;border-radius:2px}
.range::before{inset-inline:0;background:var(--sunk)}
.range::after{inset-inline-start:var(--lo);inset-inline-end:calc(100% - var(--hi));background:var(--slate)}
.range input{position:absolute;inset:0;width:100%;margin:0;background:none;appearance:none;
  pointer-events:none;height:30px}
.range input::-webkit-slider-thumb{appearance:none;pointer-events:auto;width:22px;height:22px;border-radius:100px;
  background:var(--bg);border:2px solid var(--slate);box-shadow:var(--lift);cursor:grab;position:relative;z-index:2}
.range input::-moz-range-thumb{pointer-events:auto;width:18px;height:18px;border-radius:100px;
  background:var(--bg);border:2px solid var(--slate);cursor:grab}
.range input::-webkit-slider-runnable-track{background:none}
.range input:focus-visible::-webkit-slider-thumb{outline:2px solid var(--gold);outline-offset:2px}
.range-vals{display:flex;justify-content:space-between;font-size:13px;color:var(--muted);margin-top:6px}
.range-vals b{color:var(--ink);font-weight:600}

/* quick view */
.qvbox{border:0;padding:0;border-radius:var(--r-lg);width:min(900px,calc(100vw - 32px));
  max-height:calc(100dvh - 40px);background:var(--bg);color:var(--ink);box-shadow:0 30px 80px -30px rgb(16 24 28 / .45)}
.qvbox::backdrop{background:rgba(16,24,28,.44)}
.qvbox[open]{animation:qvIn .24s cubic-bezier(.2,.7,.3,1)}
@keyframes qvIn{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
.qv-in{position:relative;display:grid;grid-template-columns:1fr 1fr;max-height:inherit}
/* The picture is pinned inside its box rather than sized by it. Safari cannot resolve a
   percentage height on a grid item whose track is sized by content, so height:100% fell
   back to the photograph's own height and a 1200px bottle ran down over the name and
   price on an iPhone. Absolutely positioned, it has a box to fill in every engine. */
.qv-gal{position:relative;overflow:hidden;background:var(--surface);display:grid;place-items:center;
  aspect-ratio:1;min-height:0}
.qv-gal img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;transition:opacity .2s ease}
.qv-gal img.swapping{opacity:.35}
.qv-gal .ph{width:38%}
.qv-info{position:relative;padding:26px 26px 22px;overflow:auto;display:flex;flex-direction:column}
/* On the box, not on the details column, so on a phone it sits on the picture's corner
   instead of halfway down the sheet. */
.qv-close{position:absolute;top:10px;inset-inline-end:10px;z-index:2;
  background:rgb(255 254 252 / .92);border-radius:100px;box-shadow:var(--lift)}
.qv-close:hover{background:var(--bg)}
.qv-info .phouse{padding-inline-end:44px}
.qv-name{font-size:22px}
.qv-actions{display:grid;grid-template-columns:1fr 1fr auto;gap:10px;margin-top:18px}
.qv-actions .fav-lg{width:48px;height:48px;border-radius:var(--r-sm)}
.qv-name{padding-inline-end:40px}
.qv-actions .add{margin-top:0;height:48px}
.add-alt{background:var(--bg);color:var(--slate);border:1.5px solid var(--slate)}
.add-alt:hover{background:var(--surface)}
.add.done{background:#2f6b4f}
.qv-piq{display:flex;flex-direction:column;gap:10px;margin-top:18px}
.qv-piq:empty{display:none}
.qv-score{display:flex;align-items:center;gap:9px}
.qv-score b{font-size:20px;font-weight:600}
.qv-more{margin-top:auto;padding-top:18px;font-size:14px;color:var(--slate);font-weight:500}
.qv-more:hover{text-decoration:underline}

/* what they looked at */
.seen{padding:22px 0 4px}
.seen h2{font-size:15px;font-weight:600;margin:0 0 12px}
.seen-row{display:flex;gap:14px;overflow-x:auto;padding-bottom:6px;scrollbar-width:thin;
  scroll-snap-type:x proximity}
.seen-item{flex:0 0 132px;display:flex;flex-direction:column;gap:5px;scroll-snap-align:start}
.seen-shot{aspect-ratio:1;background:var(--surface);border-radius:var(--r-sm);overflow:hidden;
  display:grid;place-items:center}
.seen-shot img{width:100%;height:100%;object-fit:contain;transition:transform .3s ease}
.seen-item:hover .seen-shot img{transform:scale(1.05)}
.seen-shot .ph{width:40%}
.seen-name{font-size:12.5px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.seen-price{font-size:12px;color:var(--muted)}

@media (max-width:700px){
  /* A sheet from the bottom on a phone: the thumb reaches it, and the picture stays
     small enough that the buy buttons are on the first screen. */
  .qvbox{width:100vw;max-width:100vw;max-height:92dvh;margin:auto 0 0;border-radius:var(--r-lg) var(--r-lg) 0 0}
  .qvbox[open]{animation:qvUp .28s cubic-bezier(.2,.7,.3,1)}
  @keyframes qvUp{from{transform:translateY(40px);opacity:.4}to{transform:none;opacity:1}}
  .qv-in{grid-template-columns:1fr;overflow:auto;max-height:92dvh}
  .qv-gal{aspect-ratio:auto;height:34dvh;flex:none}
  .qv-info .phouse,.qv-name{padding-inline-end:0}
  .qv-info{overflow:visible;padding:18px 16px calc(18px + env(safe-area-inset-bottom))}
  .qv-name{font-size:20px}
}
@media (max-width:560px){
  .tools{gap:10px}
  .tools-r{width:100%}
  .tool-btn,.sort select{height:44px}
  .sort{flex:1}
  .sort select{width:100%}
  .fav{width:40px;height:40px;top:8px;inset-inline-end:8px}
  /* Always there on a phone-sized screen, hover or not: a narrow window with a mouse would
     otherwise hide it until the pointer happened to cross the picture. */
  .qv-btn{opacity:1;transform:none;inset-inline:auto;inset-inline-end:8px;bottom:8px;
    width:40px;height:40px;padding:0}
  .qv-btn span{display:none}
  .fhouse{min-height:48px}
  .apill{min-height:36px}
}
@media (prefers-reduced-motion:reduce){
  .qvbox[open],.fav.on svg{animation:none!important}
  .qv-btn{transition:none!important}
}

/* ---- what customers said -------------------------------------------------------

   Laid out the way the polished review widgets do it: the score and how the votes are
   spread, then the photographs customers sent, then the reviews themselves. One five-star
   review and forty of them look identical without that middle column of bars.

   Those widgets cost a Shopify store 200-400ms of load on a phone because they are a
   third-party script that fetches its own data. This is rendered with the page, so it
   costs nothing and is in the HTML a search engine reads. */

/* Capped rather than left to fill the page. A review is prose: at the full width of a
   desktop wrap it runs past 1,100px, which is roughly 180 characters a line and about
   twice what anyone reads comfortably. The bars go narrower still — a bar the width of the
   screen stops reading as a proportion. */
.revs{border-top:1px solid var(--line);margin-top:40px;padding-top:28px;max-width:74ch}
.revs-h{font-size:20px;margin:0 0 18px}
.revs-thanks{background:#eef6f0;color:#1f5133;border-radius:var(--r-sm);padding:12px 15px;
  font-size:14px;margin:0 0 18px}
.revs-none{color:var(--faint);font-size:14px;margin:0 0 20px}

.revs-sum{display:grid;grid-template-columns:auto 1fr;gap:28px;align-items:center;
  background:var(--surface);border-radius:var(--r);padding:18px 20px;margin-bottom:18px;
  max-width:520px}
.revs-score{display:flex;flex-direction:column;align-items:center;gap:2px;
  padding-inline-end:24px;border-inline-end:1px solid var(--line-2)}
.revs-score b{font-size:38px;line-height:1;font-variant-numeric:tabular-nums}
.revs-stars{color:var(--gold);letter-spacing:.06em}
.revs-count{font-size:12px;color:var(--faint);white-space:nowrap}

.revs-bars{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
.revs-bar{display:grid;grid-template-columns:34px 1fr 28px;align-items:center;gap:10px;
  width:100%;border:0;background:none;padding:2px 0;cursor:pointer;text-align:start}
.revs-bar:disabled{cursor:default;opacity:.55}
.revs-bar-n{font-size:12px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.revs-bar-n i{font-style:normal;color:var(--gold);margin-inline-start:2px}
.revs-bar-c{font-size:12px;color:var(--faint);text-align:end;font-variant-numeric:tabular-nums}
.revs-track{height:6px;border-radius:100px;background:var(--line-2);overflow:hidden}
.revs-track b{display:block;height:100%;background:var(--gold);border-radius:100px}
.revs-bar:not(:disabled):hover .revs-track b{background:var(--slate)}
.revs-bar.is-on .revs-track b{background:var(--slate)}

.revs-wall{display:flex;gap:8px;overflow-x:auto;margin-bottom:16px;padding-bottom:2px}
.revs-wall img{width:96px;height:96px;object-fit:cover;border-radius:var(--r-sm);flex:none}

.revs-filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:20px}
.revs-clear{font-size:12.5px;color:var(--faint);cursor:pointer;text-decoration:underline}
.revs-empty{color:var(--faint);font-size:14px;margin:0 0 20px}

.revs-list{list-style:none;margin:0 0 26px;padding:0;display:flex;flex-direction:column;gap:22px}
.rev{padding-bottom:22px;border-bottom:1px solid var(--line-soft)}
.rev:last-child{border-bottom:0;padding-bottom:0}
.rev-who-row{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.rev-face{width:34px;height:34px;border-radius:100px;background:var(--slate);color:#fff;
  display:grid;place-items:center;font-size:14px;font-weight:600;flex:none}
.rev-who{display:flex;flex-direction:column;gap:1px;min-width:0}
.rev-who b{font-size:14px;font-weight:600}
.rev-ok{display:inline-flex;align-items:center;gap:3px;font-size:11px;color:#2f6b47}
.rev-when{font-size:12px;color:var(--faint);margin-inline-start:auto;white-space:nowrap}
.rev .rev-stars{font-size:13px;display:block;margin-bottom:5px}
.rev-body{margin:0;font-size:14.5px;line-height:1.65;white-space:pre-wrap}
.rev-shots{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.rev-shots img{width:88px;height:88px;object-fit:cover;border-radius:var(--r-sm)}

/* ---- writing one ---- */
.rev-form{border:1px solid var(--line-2);border-radius:var(--r);padding:16px 18px}

/* Both of these are needed. Chrome draws ::-webkit-details-marker, Safari and Firefox
   draw ::marker, and setting display:flex on the summary suppresses neither reliably —
   which is how the panel ended up with a stray triangle-turned-plus above the one the
   design had put there on purpose. */
.rev-form summary{cursor:pointer;list-style:none;display:grid;
  grid-template-columns:1fr auto;align-items:center;gap:2px 12px}
.rev-form summary::-webkit-details-marker{display:none}
.rev-form summary::marker{content:""}
.rev-form-t{font-size:15px;font-weight:600;grid-column:1}
.rev-form-s{font-size:12.5px;font-weight:400;color:var(--faint);grid-column:1}
.rev-form-v{grid-column:2;grid-row:1 / span 2;color:var(--faint);
  transition:transform .18s ease}
.rev-form[open] .rev-form-v{transform:rotate(180deg)}

/* Nothing to read yet: the form is the section, so it does not sit inside a box that
   announces its own emptiness first. */
.rev-form.is-first{border:0;padding:0}
.rev-form.is-first summary{cursor:default}
.rev-form.is-first .rev-form-v{display:none}
.rev-form.is-first .rev-form-t{font-size:16px}
.rev-form form{display:flex;flex-direction:column;gap:16px;margin-top:18px;max-width:540px}
.rev-form .co{align-self:flex-start}
.rev-err{background:#fdf2f2;color:#9a2c2c;border-radius:var(--r-sm);padding:10px 13px;
  font-size:13.5px;margin:0}
.rev-form .count{color:var(--faint);font-size:11.5px;text-align:end}

/* Real radios underneath, reversed in CSS so ":checked ~ label" lights everything to the
   left of the one chosen. The rating works on a page where no script ran, and a screen
   reader reads five choices rather than a widget. */
.rate{border:0;padding:0;margin:0}
.rate legend{padding:0;font-size:13px;color:var(--ink-2);margin-bottom:8px}
.stars{display:inline-flex;flex-direction:row-reverse;justify-content:flex-end;
  align-items:center;gap:4px;vertical-align:middle}
.stars input{position:absolute;opacity:0;width:0;height:0}
.stars label{font-size:30px;line-height:1;color:var(--line-2);cursor:pointer;
  transition:color .12s ease,transform .12s ease}
.stars input:checked ~ label,
.stars label:hover,
.stars label:hover ~ label{color:var(--gold)}
.stars label:hover{transform:scale(1.12)}
.stars input:focus-visible + label{outline:2px solid var(--slate);outline-offset:3px;
  border-radius:4px}
.rate-said{font-size:13px;color:var(--ink-2);margin-inline-start:12px}

.drop{display:flex;align-items:center;gap:10px;border:1px dashed var(--line-2);
  border-radius:var(--r-sm);padding:14px 16px;cursor:pointer;color:var(--ink-2);
  font-size:13px;transition:border-color .15s ease,background .15s ease}
.drop:hover{border-color:var(--slate);background:var(--surface)}
.drop svg{color:var(--faint);flex:none}
#revShots{position:absolute;opacity:0;width:0;height:0}
.drop-picked{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.drop-picked figure{margin:0;position:relative}
.drop-picked img{width:70px;height:70px;object-fit:cover;border-radius:var(--r-sm);display:block}

@media (max-width:560px){
  .revs-sum{grid-template-columns:1fr;gap:16px}
  .revs-score{flex-direction:row;align-items:baseline;gap:10px;padding-inline-end:0;
    border-inline-end:0;border-bottom:1px solid var(--line-2);padding-bottom:12px}
  .revs-score b{font-size:30px}
  .revs-count{margin-inline-start:auto}
}

/* A file the browser could not decode, named rather than shown as a broken icon. */
.drop-chip{display:inline-flex;align-items:center;height:70px;padding:0 12px;
  border-radius:var(--r-sm);background:var(--surface);color:var(--ink-2);font-size:12px;
  max-width:170px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drop-no{flex-basis:100%;margin:2px 0 0;font-size:12.5px;color:#9a2c2c}

/* ---- paging through a product's pictures ---------------------------------------
   The arrows sit on the picture rather than beside it, so the frame keeps its size
   whether a product has one photograph or four. */
.gal{position:relative}
.gal-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:40px;height:40px;border-radius:100px;border:1px solid var(--line-2);
  background:rgb(255 255 255 / .92);color:var(--ink);display:grid;place-items:center;
  cursor:pointer;opacity:0;transition:opacity .18s ease,background .15s ease}
.gal:hover .gal-arrow,.gal-arrow:focus-visible{opacity:1}
.gal-arrow:hover{background:#fff}
.gal-arrow:focus-visible{outline:2px solid var(--slate);outline-offset:2px}
.gal-prev{inset-inline-start:12px}
.gal-next{inset-inline-end:12px}
/* Mirrored by the writing direction: in Arabic "next" is to the left. */
[dir="rtl"] .gal-arrow svg{transform:scaleX(-1)}

.gal-tag{position:absolute;inset-inline-start:12px;bottom:12px;z-index:2;
  background:rgb(255 255 255 / .92);border-radius:100px;padding:5px 12px;
  font-size:11.5px;color:var(--ink-2)}

.gal-dots{position:absolute;inset-inline:0;bottom:12px;z-index:2;
  display:flex;justify-content:center;gap:7px;pointer-events:none}
.gal-dot{width:7px;height:7px;border-radius:100px;border:0;padding:0;
  background:var(--line-2);cursor:pointer;pointer-events:auto;transition:background .15s ease}
.gal-dot.on{background:var(--slate)}
.gal-dot:focus-visible{outline:2px solid var(--slate);outline-offset:3px}

/* A finger has no hover, so the arrows are simply always there. */
@media (hover:none){
  .gal-arrow{opacity:1}
}
@media (max-width:560px){
  .gal-arrow{width:44px;height:44px}
  .gal-prev{inset-inline-start:8px}
  .gal-next{inset-inline-end:8px}
  .gal-tag{display:none}   /* the size buttons are directly below on a phone */
}

/* A wallet number is copied by hand into another app, so it is set large and spaced. */
.wallet-no{font-size:19px;letter-spacing:.06em;font-variant-numeric:tabular-nums}
.pay-to{display:block;margin-top:3px;font-variant-numeric:tabular-nums;color:var(--ink-2)}

/* ---- the bar a thumb can reach ---------------------------------------------------

   Hidden entirely above 560px: a mouse has no reach problem and a desktop already has the
   same things across the top. */
.tabbar{display:none}

@media (max-width:560px){
  .tabbar{
    position:fixed;inset-inline:0;bottom:0;z-index:70;
    display:grid;grid-template-columns:repeat(6,1fr);align-items:stretch;
    /* The home indicator sits in the bottom ~34px of a modern iPhone and will happily sit
       on top of a label. */
    padding:6px 6px calc(6px + env(safe-area-inset-bottom));

    /* Glass. The blur is the effect; the translucent fill is only what the blur needs to
       tint. Where backdrop-filter is unsupported the fill below takes over on its own. */
    background:rgb(252 252 251 / .72);
    backdrop-filter:saturate(180%) blur(20px);
    -webkit-backdrop-filter:saturate(180%) blur(20px);
    border-top:1px solid rgb(255 255 255 / .55);
    box-shadow:0 -1px 0 rgb(20 22 26 / .06), 0 -12px 28px -20px rgb(20 22 26 / .45);
  }
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
    .tabbar{background:var(--bg)}
  }

  .tab{
    position:relative;border:0;background:none;padding:7px 2px 5px;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    min-height:50px;color:var(--faint);font:inherit;font-size:10.5px;letter-spacing:.01em;
    cursor:pointer;text-decoration:none;-webkit-tap-highlight-color:transparent;
    transition:color .18s ease;
  }
  .tab svg{width:23px;height:23px;transition:transform .22s cubic-bezier(.2,.8,.3,1)}
  .tab span{line-height:1}

  /* The current place, and the one being pressed, are the only two states worth drawing. */
  .tab.on{color:var(--ink)}
  .tab.on svg{transform:translateY(-1px)}
  .tab:active svg{transform:scale(.88)}
  .tab:focus-visible{outline:2px solid var(--slate);outline-offset:-4px;border-radius:12px}

  /* A soft pill behind the current tab rather than a hard underline: the bar is glass and
     a rule drawn on it reads as a crack. */
  .tab.on::before{
    content:"";position:absolute;inset:2px 6px auto;height:34px;border-radius:12px;
    background:rgb(20 22 26 / .055);
  }

  .tab-count{
    position:absolute;top:3px;inset-inline-end:calc(50% - 20px);
    min-width:16px;height:16px;padding:0 4px;border-radius:100px;
    background:var(--slate);color:#fff;font-size:10px;font-style:normal;line-height:16px;
    text-align:center;font-variant-numeric:tabular-nums;
  }

  /* Room for the bar, so the last row of the catalogue is not sitting under it. */
  main{padding-bottom:calc(74px + env(safe-area-inset-bottom))}
  footer{padding-bottom:calc(30px + 74px + env(safe-area-inset-bottom))}

  /* The cart drawer and the search panel have to clear it too. */
  .cart .cfoot{padding-bottom:calc(16px + 74px + env(safe-area-inset-bottom))}

  /* With the bar carrying search, the bag and the account, the top of the screen is only
     the mark and the language — which is all a customer needs to know where they are. */
  .searchbtn{display:none}
  .hacts .icon{display:none}
  /* The mark is positioned absolutely, so with the search and the bag gone the language
     switch is the only child left in flow — and space-between puts a lone child at the
     start. Pin it to the end, where it was. */
  .hacts{margin-inline-start:auto}
}

@media (max-width:560px) and (prefers-reduced-motion:reduce){
  .tab svg{transition:none}
}

/* ---- bundles ------------------------------------------------------------------
   The campaign card is the picture, so the card around it stays quiet: name, the line
   from the card, what is inside, the price against what the five would cost apart. */
.bx-head{padding:26px 0 8px;max-width:640px}
.bx-head h1{font-size:30px;line-height:1.15;margin:0 0 10px;letter-spacing:-.01em}
.bx-head p{margin:0;color:var(--ink-2)}
.bx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));gap:26px;padding:22px 0 60px}
.bx{min-width:0;display:flex;flex-direction:column;background:var(--bg);border:1px solid var(--line);
  border-radius:var(--r-lg);overflow:hidden}
.bx-art{position:relative;display:block;aspect-ratio:1080/850;background:#fff;border-bottom:1px solid var(--line-soft)}
.bx-art img{width:100%;height:100%;max-width:100%;display:block;object-fit:contain}
.bx.is-out .bx-art img{opacity:.55;filter:grayscale(.35)}
.bx-out{position:absolute;top:14px;inset-inline-start:14px;background:var(--slate);color:#fff;
  font-size:12.5px;font-weight:500;padding:6px 12px;border-radius:100px}
.bx-body{display:flex;flex-direction:column;gap:6px;padding:16px 20px 20px;flex:1}
.bx-name{font-size:19px;font-weight:600;margin:0}.bx-name a{color:inherit;text-decoration:none}.bx-name a:hover{text-decoration:underline}
.bx:has(.bx-art:hover) .bx-name a{text-decoration:underline}
.bx-tag{margin:0;color:var(--ink-2)}
.bx-size{margin:0;font-size:13.5px;font-weight:500}.bx-size span{color:var(--muted);font-weight:400}
.bx-price{display:flex;align-items:baseline;flex-wrap:wrap;gap:10px;margin-top:auto;padding-top:6px}
.bx-price b{font-size:22px;font-weight:600}
.bx-price s{color:var(--faint);font-size:14px}
.bx-save{font-size:12.5px;color:var(--gold);font-weight:600}
.bx-add{width:100%;margin-top:6px}
.bx-add[disabled]{background:var(--sunk);color:var(--muted);cursor:not-allowed}
.bx-add.done{background:var(--slate-hi)}
.chip-bundles{font-weight:600}
@media (max-width:560px){
  .bx-head h1{font-size:25px}
  .bx-grid{grid-template-columns:1fr;gap:18px}
}

/* ---- one bundle ---- */
.bd{padding-bottom:60px}
.bd-back{display:inline-block;margin:18px 0 6px;color:var(--muted);font-size:14px}
.bd-back::before{content:"← "}
[dir=rtl] .bd-back::before{content:"→ "}
.bd-grid{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:40px;align-items:start;padding-top:10px}
.bd-art{position:relative;background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.bd-art img{width:100%;height:auto;display:block}
.bd-info{display:flex;flex-direction:column;gap:10px}
.bd-info h1{font-size:30px;line-height:1.15;margin:0}
.bd-tag{margin:0;font-size:17px;color:var(--ink-2)}
.bd-price{margin-top:6px}
.bd-vs{margin:-4px 0 4px;font-size:13.5px;color:var(--muted)}
.bd-sec{border-top:1px solid var(--line);margin-top:14px;padding-top:16px}
.bd-sec h2{font-size:15px;font-weight:600;margin:0 0 10px}
.bd-sec p{margin:0;color:var(--ink-2)}
.bd-parts{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.bd-part{display:grid;grid-template-columns:48px 1fr auto;align-items:center;gap:12px;
  padding:6px;border-radius:var(--r-sm);color:inherit;text-decoration:none}
a.bd-part:hover{background:var(--surface)}
.bd-th{width:48px;height:48px;border-radius:8px;background:var(--surface);overflow:hidden;display:grid;place-items:center}
.bd-th img{width:100%;height:100%;object-fit:contain}
.bd-pn{font-weight:500;text-align:start}
.bd-pp{font-size:13px;color:var(--muted);white-space:nowrap}
.bd-part.is-missing .bd-pn{color:var(--muted)}
@media (max-width:760px){
  .bd-grid{grid-template-columns:1fr;gap:20px}
  .bd-info h1{font-size:25px}
}

/* Nothing is selected until the shopper says so, and Add says so when it is pressed early. */
.pick-warn{margin:8px 0 0;color:var(--low);font-size:13.5px;font-weight:500}
.vars.needs-pick .var:not([disabled]){border-color:var(--low)}
@media (prefers-reduced-motion:no-preference){
  .vars.needs-pick{animation:nudge .32s ease}
}
@keyframes nudge{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}

/* ---- the words on a catalogue page -------------------------------------------------

   A shop made only of product cards has nothing of its own to say — to a reader who has
   just arrived, or to a search engine deciding what this page is about. These are the
   few paragraphs that do the saying, so they are set as text to read rather than as
   another control: measured line length, and never wider than a paragraph should be. */

.intro{max-width:62ch;margin:18px 0 2px;color:var(--ink-2);font-size:15px;line-height:1.65}

/* Every house, linked, at the foot of the catalogue. Quiet by design: this is a way
   through the shop for someone who arrived knowing the name of one house, not a feature
   competing with the grid above it. */
.houses{border-top:1px solid var(--line);padding:26px 0 60px}
.houses h2{font-size:15px;font-weight:600;margin:0 0 12px}
.house-row{display:flex;flex-wrap:wrap;gap:8px}
.house-row a{border:1px solid var(--line-2);border-radius:100px;padding:7px 15px;
  font-size:13.5px;color:var(--ink-2);background:var(--bg)}
.house-row a:hover{border-color:var(--slate);color:var(--ink)}
.house-row a[aria-current="page"]{background:var(--slate);border-color:var(--slate);color:#fff}

/* The questions page. One column, because it is read top to bottom. */
.page{padding-bottom:72px}
.page h1{font-size:26px;font-weight:600;margin:14px 0 0;letter-spacing:-.01em}
.faq{max-width:68ch;margin-top:26px;display:flex;flex-direction:column;gap:26px}
.faq h2{font-size:16.5px;font-weight:600;margin:0 0 7px}
.faq p{margin:0;color:var(--ink-2);font-size:15px;line-height:1.7}

/* The footer is four columns spread apart on a wide screen. Wrapped onto a phone, that
   spreading left three columns on the left and pushed the fourth against the right edge
   as a narrow strip with its links broken across lines. Two even columns instead, all
   starting at the same margin as the rest of the page. */
@media (max-width:560px){
  .fgrid{display:grid;grid-template-columns:1fr 1fr;gap:22px 18px}
}

/* The footer is four columns spread apart on a wide screen. Wrapped onto a phone, that
   spreading left three columns on the left and pushed the fourth against the right edge
   as a narrow strip with its links broken across lines. Two even columns instead, all
   starting at the same margin as the rest of the page. */
@media (max-width:560px){
  .fgrid{display:grid;grid-template-columns:1fr 1fr;gap:22px 18px}
}
