
@font-face{font-family:'Montserrat';src:url('/fonts/montserrat-var.woff2') format('woff2');font-weight:100 900;font-style:normal;font-display:swap}
/* ============================================================
   Wall Boulevard — iOS design language
   ============================================================ */
:root{
  --sp:  cubic-bezier(.32,.72,0,1);
  --sp2: cubic-bezier(.4,.8,.2,1);

  --tint:#0B6FB0;
  --tint-soft:#E3F0FA;
  --tint-ink:#09609A;
  --ink:#2B2D31;

  --bg:#F2F2F7;
  --bg-elev:#FFFFFF;
  --bg-elev2:#FFFFFF;
  --fill:rgba(120,120,128,.12);
  --fill2:rgba(120,120,128,.16);
  --label:#000;
  --label2:rgba(60,60,67,.8);
  --label3:rgba(60,60,67,.3);
  --sep:rgba(60,60,67,.29);
  --sep-op:rgba(60,60,67,.10);
  --navbar:rgba(249,249,249,.80);
  --shadow:0 1px 2px rgba(0,0,0,.04),0 8px 28px rgba(0,0,0,.06);
  --shadow-lg:0 4px 12px rgba(0,0,0,.08),0 24px 60px rgba(0,0,0,.14);
  --radius:18px;
  --radius-card:12px;
  --hair:.5px;
}
[data-theme="dark"]{
  --tint:#2DB4F2;
  --tint-soft:rgba(45,180,242,.14);
  --tint-ink:#2DB4F2;
  --ink:#EDEDF0;
  --bg:#000;
  --bg-elev:#1C1C1E;
  --bg-elev2:#2C2C2E;
  --fill:rgba(120,120,128,.24);
  --fill2:rgba(120,120,128,.32);
  --label:#fff;
  --label2:rgba(235,235,245,.6);
  --label3:rgba(235,235,245,.3);
  --sep:rgba(84,84,88,.65);
  --sep-op:rgba(235,235,245,.12);
  --navbar:rgba(22,22,24,.80);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 8px 28px rgba(0,0,0,.5);
  --shadow-lg:0 4px 12px rgba(0,0,0,.5),0 24px 60px rgba(0,0,0,.7);
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--label);
  font-family:'Montserrat',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  font-size:17px;line-height:1.47;letter-spacing:-.01em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
body.no-scroll{overflow:hidden}
img{display:block;max-width:100%}
a{color:var(--tint);text-decoration:none}
button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
:focus-visible{outline:2.5px solid var(--tint);outline-offset:2px}
a:not([class]):focus-visible{border-radius:6px}

/* ---------- type ---------- */
/* v72 — product names carry unspaced tokens the browser cannot break
   ("Wheelbarrow/Chunky", 18"/457mm). Without this they push the whole page
   sideways on a phone: 4px at 390px, 74px at 320px. 326 of 1,276 trade
   products share the pattern, so this one rule covers the latent cases too. */
.lg-title{font-size:34px;line-height:1.12;font-weight:700;letter-spacing:-.028em;overflow-wrap:anywhere;word-break:break-word}
.t1{font-size:28px;line-height:1.17;font-weight:700;letter-spacing:-.024em}
.t2{font-size:22px;line-height:1.24;font-weight:700;letter-spacing:-.021em}
.t3{font-size:20px;line-height:1.26;font-weight:600;letter-spacing:-.018em}
.headline{font-size:17px;font-weight:600;letter-spacing:-.012em}
.body{font-size:17px;max-width:70ch}
.callout{font-size:16px;letter-spacing:-.008em}
.subhead{font-size:15px;letter-spacing:-.006em}
.foot{font-size:13px;letter-spacing:-.002em}
.cap{font-size:12px;letter-spacing:0}
.dim{color:var(--label2)}
.dim3{color:var(--label3)}
.tint{color:var(--tint)}
.up{text-transform:uppercase;letter-spacing:.06em;font-weight:600;font-size:12.5px}
.tnum{font-variant-numeric:tabular-nums}

/* ---------- layout ---------- */
.wrap{max-width:var(--maxw,1120px);margin:0 auto;padding:0 var(--gut,20px)}
.wrap-n{max-width:760px;margin:0 auto;padding:0 var(--gut,20px)}
main{padding-bottom:calc(64px + env(safe-area-inset-bottom) + 24px);min-height:100vh}
@media(min-width:900px){main{padding-bottom:40px}}
section{scroll-margin-top:120px}
.stack>*+*{margin-top:14px}
.mt8{margin-top:8px}.mt16{margin-top:16px}.mt24{margin-top:24px}.mt32{margin-top:32px}.mt44{margin-top:44px}
.center{text-align:center}

/* ---------- nav bar (Liquid Glass, edge to edge) ---------- */
/* v84 made the header a floating glass capsule. v85 — Nick: "the Liquid Glass
   rounded the top edges of the WB banner, can it be squared off to the edge
   instead?" — keeps the glass material (same tokens as the tab bar) but runs it
   full width and square again: a specular hairline along the bottom edge, and a
   soft drop shadow once the page has scrolled under it. --navi is 0, so every
   offset that hangs off the header is back where it was in v83. */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:60;
  background:var(--glass-bg);
  border-bottom:1px solid var(--glass-edge);
  box-shadow:0 1px 0 0 var(--glass-spec) inset;
  padding-top:env(safe-area-inset-top);
  isolation:isolate;
  transition:box-shadow .3s var(--sp2),border-color .3s;
}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .nav{-webkit-backdrop-filter:blur(26px) saturate(200%) brightness(1.06);backdrop-filter:blur(26px) saturate(200%) brightness(1.06)}
}
.nav.scrolled{border-bottom-color:var(--sep-op);box-shadow:0 1px 0 0 var(--glass-spec) inset,0 10px 30px -14px rgba(0,0,0,.28)}
/* v23: nav gutter matches the content gutter exactly, so the logo's left edge
   lines up with the page title and cards below it (the logo SVG has no
   built-in padding — its ink starts at x=0 — so no optical offset is needed) */
.nav-in{height:var(--navh);display:flex;align-items:center;gap:14px;max-width:var(--maxw,1120px);margin:0 auto;padding:0 var(--gut,20px)}
/* accessibility + old browsers: opaque bars where blur is unavailable or unwanted */
@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .nav,.tsel-bar,.sheet-head{background:var(--bg-elev)}
}
@media(prefers-reduced-transparency:reduce){
  .nav,.tabbar,.tsel-bar,.sheet-head{background:var(--bg-elev);-webkit-backdrop-filter:none;backdrop-filter:none}
}
/* v85 — press feedback (Nick: "show that the press of the button makes the button
   illuminate or show feedback as it directs you"). iOS Safari only paints :active
   for touches once a touchstart listener exists (boot adds one); .pressed mirrors
   :active from pointer events so the squeeze shows everywhere; .lit is the glow a
   button gives off as it sends you somewhere. */
.btn.pressed{transform:scale(.965);filter:brightness(1.1)}
.tab.pressed,.chip.pressed{transform:scale(.94)}
.cchip.pressed,.tbtn.pressed{transform:scale(.93)}
a.card.pressed,button.card.pressed{transform:scale(.982)}
.tcard.pressed{transform:scale(.965)}
.row.link.pressed{background:var(--fill)}
.icon-btn.pressed,.ig-tile.pressed,.call-tile.pressed,.tsel-arrow.pressed{transform:scale(.9)}
.sw.pressed{transform:scale(.96)}
.cd-store.pressed,.call-btn.pressed{transform:scale(.95)}
.btn{--lit:rgba(11,111,176,.55)}
[data-theme="dark"] .btn{--lit:rgba(45,180,242,.55)}
.btn.sec,.btn.ghost{--lit:rgba(11,111,176,.42)}
.hero .btn,.hero .btn.ghost{--lit:rgba(255,255,255,.75)}
.btn.lit{animation:btnLit .62s var(--sp2) both}
@keyframes btnLit{
  0%{box-shadow:0 0 0 0 var(--lit);filter:brightness(1.22)}
  100%{box-shadow:0 0 0 16px transparent;filter:brightness(1)}
}
/* v85 — page changes crossfade instead of cutting (Nick: "smooth, not just a full
   BANG into the next option"). View Transitions API where it exists (Safari 18+,
   Chrome, Firefox 144+): the old page fades out as the new one rises in; the
   header and tab bar are their own groups so they never blink. vt-quick is the
   shorter version used when only the tile grid changes under a filter. */
::view-transition-old(root){animation:vtOut .2s ease both}
::view-transition-new(root){animation:vtIn .34s var(--sp) both}
@keyframes vtOut{to{opacity:0}}
@keyframes vtIn{from{opacity:0;transform:translateY(8px)}}
@keyframes vtFade{from{opacity:0}}
html.vt-quick::view-transition-old(root){animation-duration:.12s}
html.vt-quick::view-transition-new(root){animation:vtFade .22s ease both}
.nav{view-transition-name:wb-nav}
.tabbar{view-transition-name:wb-tabbar}
html.vt .view{animation:none}
html.restoring{overflow-anchor:none}   /* the transition does the entrance; no double fade */
@media(prefers-reduced-motion:reduce){
  .btn.lit{animation:none}
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}
}
/* v85 — back button on breadcrumb pages (Nick: "can you insert a back button?") */
.backbtn{display:inline-flex;align-items:center;gap:1px;margin:0 10px 0 0;padding:6px 12px 6px 6px;border-radius:999px;
  background:var(--bg-elev2);color:var(--tint);box-shadow:inset 0 0 0 1px var(--sep-op);font-weight:600;font-size:13.5px;letter-spacing:-.006em;line-height:1;
  transition:transform .14s var(--sp),background .18s}
.backbtn svg{transform:rotate(180deg)}
.backbtn:hover{background:var(--tint-soft)}
.backbtn:active,.backbtn.pressed{transform:scale(.94)}
.crumbs .backbtn span{padding:0}
/* v88 — trade page brand strip: a slim marquee. Wordmarks until logo files arrive. */
.brandstrip{overflow:hidden;margin:6px 0 0;padding:10px 0;border-top:var(--hair) solid var(--sep-op);border-bottom:var(--hair) solid var(--sep-op);
  /* v120 — Luke: "the maxisil logo is cut off". The fade was 8% of the strip, so on a phone it ate ~29px and
     hard-clipped the widest wordmark. A fixed 38px behaves the same at every width. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 38px,#000 calc(100% - 38px),transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 38px,#000 calc(100% - 38px),transparent 100%)}
.bs-track{display:flex;align-items:center;gap:22px;width:max-content;animation:bsScroll 38s linear infinite}
.brandstrip:hover .bs-track{animation-play-state:paused}
.bs-item{display:inline-flex;align-items:center;color:var(--label2);text-decoration:none;flex:0 0 auto}
a.bs-item:hover{color:var(--tint)}
.bs-word{font-weight:800;font-size:13px;letter-spacing:.14em;white-space:nowrap}
.bs-item img{height:24px;width:auto;display:block}  /* v94 — no chip: real vector, light + dark versions swapped by theme */
/* v95 — ARDEX's lockup is near-square (283x245), so at a shared height it towers over the
   wordmarks. Optical sizing per brand keeps the row on one baseline. */
.bs-item img[src*="brand-ardex"]{height:29px}
.bs-item img[src*="brand-sika"]{height:30px}
/* v96 — the last seven. Square-ish marks (BAT's roundel, DTA's map, the Fliese box) need a
   touch more height than a wordmark to read at the same optical weight. */
.bs-item img[src*="brand-bat"]{height:30px}
.bs-item img[src*="brand-dta"]{height:29px}
.bs-item img[src*="brand-fliese"]{height:27px}
.bs-item img[src*="brand-sas"]{height:27px}
.bs-item img[src*="brand-gripset"]{height:26px}
.bs-item .bs-d{display:none}
[data-theme="dark"] .bs-item .bs-l{display:none}
[data-theme="dark"] .bs-item .bs-d{display:block}
/* v96 — Nick: "maybe use a vertical line instead of a dot like the wb has". The Wall
   Boulevard mark uses an upright rule between words, so the strip now echoes it. */
.bs-sep{width:1px;height:16px;background:var(--label3);opacity:.5;flex:0 0 auto}
/* v121 — save-for-later list */
.list-btn{position:relative}
.list-badge{position:absolute;top:1px;right:0;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--tint);color:#fff;font:800 10px/16px 'Montserrat',sans-serif;text-align:center;box-shadow:0 0 0 2px var(--bg-elev)}
.li-row{display:flex;gap:12px;align-items:center;padding:12px 0;border-bottom:.5px solid var(--sep-op)}
.li-row:last-child{border-bottom:0}
.li-row .lt{width:46px;height:46px;border-radius:9px;background:var(--tint-soft);display:grid;place-items:center;flex:0 0 auto;overflow:hidden}
.li-row .lt img{width:100%;height:100%;object-fit:cover}
.li-row .lt svg{width:22px;height:22px;color:var(--tint)}
.li-row .li-info{flex:1;min-width:0}
.li-row .li-n{font-size:14px;font-weight:600;line-height:1.25}
.li-row .li-b{font-size:12px;color:var(--label2)}
.note.tshow{display:flex;gap:11px;align-items:flex-start}
.note.tshow>svg{flex:0 0 auto;margin-top:2px}
.tshow-c{display:flex;flex-direction:column;gap:11px;flex:1;min-width:0}
.tshow-h{font-size:15.5px}
.tshow-row{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.tshow-s{display:flex;flex-direction:column;gap:2px;font-size:13.5px;line-height:1.4}
.tshow-s>b{font-size:14px;color:var(--label)}
.tshow-s>span{color:var(--label2)}
@media(max-width:600px){.tshow-row{grid-template-columns:1fr;gap:14px}}
.lqty{display:flex;align-items:center;gap:3px}
.lqty button{width:44px;height:44px;margin:0 -8px;position:relative;isolation:isolate;border:0;background:none;font-size:16px;line-height:1;cursor:pointer;color:var(--ink)}
.lqty button::before{content:"";position:absolute;inset:8px;z-index:-1;border:1px solid var(--sep);background:var(--bg-elev);border-radius:8px}
.lqty span{min-width:24px;text-align:center;font-weight:700;font-size:14px}
.lrm{border:0;background:none;color:var(--label2);cursor:pointer;font-size:12px;padding:6px 8px;min-height:44px}
.lstores{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:2px 0 16px}
.lstore{display:flex;align-items:center;gap:11px;border:1.5px solid var(--sep);border-radius:12px;padding:13px 14px;cursor:pointer;background:var(--bg-elev);transition:border-color .14s, background .14s;text-align:left}
.lstore:hover{border-color:var(--label3)}
.lstore.sel{border-color:var(--tint);background:var(--tint-soft)}
.lstore .lstore-txt{flex:1;min-width:0}
.lstore b{font-size:14px;display:block;line-height:1.3}
.lstore .role{display:block;font-size:12px;color:var(--label2);margin-top:1px}
.lstore .tick{flex:0 0 auto;width:19px;height:19px;border-radius:999px;border:1.5px solid var(--sep);background:var(--bg-elev);display:grid;place-items:center;transition:border-color .14s, background .14s}
.lstore .tick svg{width:11px;height:11px;opacity:0;transition:opacity .14s}
.lstore.sel .tick{border-color:var(--tint);background:var(--tint)}
.lstore.sel .tick svg{opacity:1}
.lfields{display:grid;grid-template-columns:1fr 1fr;gap:11px;margin-bottom:14px}
.lfield.full{grid-column:1 / -1}
.lfield label{display:block;font-size:12px;font-weight:600;color:var(--label2);margin-bottom:5px}
.lfield .opt{font-weight:500;color:var(--label2)}
.lfield input{width:100%;border:1px solid var(--sep);border-radius:10px;padding:11px 12px;font:400 14px/1.2 'Montserrat',sans-serif;background:var(--bg-elev);color:var(--ink)}
.lfield input:focus{outline:2px solid var(--tint-soft);border-color:var(--tint)}
.lsecondary{display:flex;gap:10px;margin-top:10px}
.lsecondary .btn{flex:1}
.lshare{font-size:12px;background:var(--bg);border:1px solid var(--sep);border-radius:10px;padding:11px 13px;margin-top:12px;word-break:break-all;color:var(--label2);line-height:1.5}
.addrow{display:flex;gap:6px;align-items:stretch}
.addrow-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;border:1px solid var(--sep);border-radius:10px;padding:11px 8px;font:700 13.5px/1 'Montserrat',sans-serif;cursor:pointer;background:var(--bg-elev);color:var(--ink);text-decoration:none;white-space:nowrap}
.addrow-btn.added{background:var(--tint-soft);border-color:var(--tint);color:var(--tint)}
.addrow-btn.view{color:var(--tint)}
.addrow-minus{flex:0 0 auto;width:44px;border:1px solid var(--sep);border-radius:10px;background:var(--bg-elev);font-size:20px;line-height:1;cursor:pointer;color:var(--label2)}
.addrow-minus:hover,.addrow-btn:hover{border-color:var(--label3)}
.lsendnote{font-size:12px;color:var(--label2);margin:10px 2px 0;line-height:1.45}
.bnr{border-radius:14px;overflow:hidden;display:flex;align-items:stretch;min-height:176px;margin-bottom:18px}
.bnr-txt{flex:1;padding:24px 26px;display:flex;flex-direction:column;justify-content:center;gap:7px}
.bnr-mark{font:900 23px/1 'Montserrat',sans-serif;letter-spacing:.02em}
.bnr-h{font:800 24px/1.05 'Montserrat',sans-serif;margin:0}
.bnr-p{font-size:13.5px;line-height:1.45;max-width:420px;opacity:.93;margin:0}
.bnr-pill{display:inline-flex;align-self:flex-start;margin-top:5px;font:700 12.5px/1 'Montserrat',sans-serif;padding:7px 13px;border-radius:999px}
.bnr-art{flex:0 0 40%;display:flex;align-items:center;justify-content:center;padding:18px}
.bnr-art img{max-width:100%;max-height:148px;object-fit:contain;border-radius:8px;background:#fff}
.bnr-sw{display:grid;grid-template-columns:repeat(8,1fr);gap:5px;width:100%;max-width:360px}
.bnr-sw span{aspect-ratio:1;border-radius:6px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.28)}
.bnr-sw span{cursor:pointer} .bnr-sw span{transition:transform .12s ease,box-shadow .12s ease} .bnr-sw span.big{transform:scale(1.4);box-shadow:0 3px 12px rgba(0,0,0,.4);position:relative;z-index:2}
.bnr-sw span.cadded{outline:2px solid #fff;outline-offset:2px}
.cc.cadded{outline:2px solid var(--tint);outline-offset:1px} .cchart .cc.sel{outline:2px solid var(--tint);outline-offset:1px} .cchart .cc{cursor:pointer} .cpick{margin-top:12px;display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;background:var(--bg-elev);border-radius:12px;padding:12px 14px;box-shadow:var(--shadow)} .cpick-lbl{display:flex;align-items:center;gap:9px;font-weight:600} .cpick-sw{width:26px;height:26px;border-radius:50% 50% 50% 4px;flex:0 0 auto;box-shadow:inset 0 0 0 .5px rgba(0,0,0,.12)} .cpick-nm{font-size:14px} .cpick-add{flex:1;min-width:200px}
.li-col{color:var(--label2);font-weight:600}
.wb-toast{position:fixed;left:50%;bottom:22px;transform:translateX(-50%) translateY(8px);background:#14181f;color:#fff;padding:11px 18px;border-radius:999px;font-size:13.5px;font-weight:600;box-shadow:0 8px 28px rgba(0,0,0,.34);opacity:0;transition:opacity .18s,transform .18s;z-index:9999;pointer-events:none;max-width:90vw;text-align:center}
.wb-toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
.bnr-board{width:150px;height:112px;background:linear-gradient(135deg,#f4efe4,#e6dcc6);border-radius:8px;transform:rotate(-7deg);box-shadow:0 10px 22px rgba(0,0,0,.22);display:grid;place-items:center;font:800 10px/1 'Montserrat',sans-serif;letter-spacing:.04em;text-align:center}
.bnr-mapei{background:linear-gradient(120deg,#0a4fa0,#0866c9);color:#fff}
.bnr-mapei .bnr-pill{background:#fff;color:#0a4fa0}
.bnr-mapei .bnr-art{background:rgba(255,255,255,.06)}
.bnr-monsoon{background:linear-gradient(120deg,#0e6f78,#0b8f88);color:#fff}
.bnr-monsoon .bnr-pill{background:#eafcff;color:#0e6f78}
.bnr-monsoon .bnr-art{background:rgba(255,255,255,.07)}
.bnr-monsoon .bnr-board{color:#0e6f78}
.bnr-wedi{background:linear-gradient(120deg,#c8801f,#e0a53a);color:#fff}
.bnr-wedi .bnr-pill{background:#fff;color:#b0701a}
.bnr-wedi .bnr-art{background:rgba(255,255,255,.08)}
.bnr-ardex{background:linear-gradient(120deg,#333f48,#50626d);color:#fff}
.bnr-ardex .bnr-pill{background:#fff;color:#333f48}
.bnr-ardex .bnr-art{background:rgba(255,255,255,.08)}
.bnr-sika{background:linear-gradient(120deg,#2b2b2b,#4a4a4a);color:#fff}
.bnr-sika .bnr-pill{background:#FEDD00;color:#1a1a1a}
.bnr-sika .bnr-art{background:rgba(255,255,255,.08)}
.bnr-wedi .bnr-board{color:#b0701a}
@media(max-width:640px){.bnr{flex-direction:column;min-height:0}.bnr-art{flex-basis:auto;padding-top:2px}.bnr-sw{max-width:540px;grid-template-columns:repeat(10,1fr)}}
@media(max-width:520px){.lstores{grid-template-columns:1fr}.lfields{grid-template-columns:1fr}}

@keyframes bsScroll{to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){.bs-track{animation:none;flex-wrap:wrap;width:auto}.brandstrip{-webkit-mask-image:none;mask-image:none}}
.g-cats{grid-template-columns:repeat(3,1fr)}
@media(max-width:640px){.g-cats{grid-template-columns:repeat(2,1fr);gap:11px}}
/* v88 — Nick: "instead of dots in between, do a line like the WB logo has" */
.badge .vsep{width:1px;height:.95em;background:currentColor;opacity:.45;flex:0 0 auto;margin:0 2px}
.hero-status .badge .vsep{opacity:.6}
/* v88 — Nick: "the dots aren't centred on that image" */
.hero-dots,.hero-bleed .hero-dots{left:50%;right:auto;transform:translateX(-50%)}
/* v88 — a 500px chip name made the filter sheet scroll sideways; never again */
.sheet{overflow-x:hidden}
#sheetBody .cchip{white-space:normal;text-align:left;max-width:100%}
/* v88 — Nick: tile sheet buttons "both the same, go across the screen" */
.sheet-btns{display:flex;flex-direction:column;gap:10px}
/* v93 — the two-store chooser rows: name + pill, address, number, stacked */
.csr{align-items:flex-start}
.csm{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
.cst{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.csp{font-size:15.5px;font-weight:600;color:var(--tint);margin-top:2px}
.sheet-btns .btn{width:100%}
/* v88 — product colour chart (Ultracolor Plus first) */
.cchart{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.cchart .cc{display:flex;align-items:center;gap:10px;background:var(--bg-elev);border-radius:12px;padding:8px 10px;box-shadow:var(--shadow)}
.cchart .cc i{width:30px;height:30px;border-radius:50% 50% 50% 4px;flex:0 0 auto;box-shadow:inset 0 0 0 .5px rgba(0,0,0,.12)}
.cchart .cc i.tr{background:linear-gradient(135deg,rgba(255,255,255,.95),rgba(255,255,255,.3)),repeating-conic-gradient(#d9d9de 0 25%,#f4f4f7 0 50%) 50%/8px 8px}
.cchart a.cc{text-decoration:none;color:inherit;transition:box-shadow .15s,transform .15s;cursor:pointer}
.cchart a.cc:hover{box-shadow:0 0 0 1.5px var(--tint) inset,var(--shadow);transform:translateY(-1px)}
.cchart a.cc.cc-cur{box-shadow:0 0 0 2px var(--tint) inset,var(--shadow)}
.cchart .cc-you{display:block;font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-style:normal;color:var(--tint);margin-top:2px}
.cchart .cc b{display:block;font-size:12px;color:var(--label2);font-weight:600;letter-spacing:.02em}
.cchart .cc span{display:block;font-size:13.5px;font-weight:600;line-height:1.2}
.brand{display:flex;align-items:center;gap:9px;font-weight:700;font-size:16.5px;letter-spacing:-.02em;color:var(--label);flex-shrink:0}
.brand .mark{
  width:29px;height:29px;border-radius:8px;background:var(--ink);color:#fff;
  display:grid;place-items:center;font-size:11.5px;font-weight:800;letter-spacing:.01em;flex-shrink:0
}
[data-theme="dark"] .brand .mark{background:var(--tint);color:#062233}
.nav-title{
  position:absolute;left:50%;transform:translateX(-50%) translateY(6px);
  font-size:16.5px;font-weight:600;letter-spacing:-.012em;
  opacity:0;transition:opacity .26s var(--sp2),transform .26s var(--sp2);
  pointer-events:none;white-space:nowrap;max-width:52%;overflow:hidden;text-overflow:ellipsis
}
.nav.compact .nav-title{opacity:1;transform:translateX(-50%) translateY(0)}
.nav.compact .brand{opacity:0;transition:opacity .2s}
@media(min-width:900px){.nav.compact .brand{opacity:1}.nav-title{display:none}}
.nav-links{display:none;gap:2px;margin-left:6px}
@media(min-width:900px){.nav-links{display:flex}}
.nav-links a{
  color:var(--label);font-size:14.5px;font-weight:500;letter-spacing:-.008em;
  padding:7px 11px;border-radius:9px;transition:background .18s,color .18s
}
.nav-links a:hover{background:var(--fill)}
.nav-links a.on{color:var(--tint);background:var(--tint-soft)}
.nav-right{margin-left:auto;display:flex;align-items:center;gap:0;margin-right:-7px}
.icon-btn{
  width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  color:var(--tint);transition:background .18s,transform .12s var(--sp);
  position:relative
}
/* v24: pad the hit area out to 44px without changing the visual */
.icon-btn::after{content:"";position:absolute;inset:0;border-radius:50%}
/* v24: inline phone-number links (footer, store cards) were 16px-tall tap
   targets — the most important tap on the site. Padding + negative margin
   grows the hit box to ~28px with zero visual change. */
.foot a[href^="tel:"]{display:inline-block;padding:6px 0;margin:-6px 0}
.icon-btn:hover{background:var(--fill)}
.icon-btn:active{transform:scale(.9)}
.call-btn{
  display:none;align-items:center;gap:6px;background:var(--tint);color:#fff;
  padding:7px 15px;border-radius:999px;font-size:14px;font-weight:600;letter-spacing:-.006em;
  transition:transform .14s var(--sp),filter .18s
}
[data-theme="dark"] .call-btn{color:#04231a}
.call-btn:active{transform:scale(.95)}
.call-btn:hover{filter:brightness(1.08)}
@media(min-width:620px){.call-btn{display:inline-flex}}

/* ---------- large title ---------- */
.page-head{padding:calc(env(safe-area-inset-top) + var(--navh) + var(--navi,0px) + 16px) var(--gut,20px) 6px}
.page-head .eyebrow{color:var(--tint);font-weight:600;font-size:13px;letter-spacing:.04em;text-transform:uppercase;margin-bottom:5px}
.page-head p.sub{color:var(--label2);font-size:17px;margin:9px 0 0;max-width:620px}

/* ---------- tab bar ---------- */
/* v63 — Liquid Glass tab bar. A floating capsule that refracts the page
   behind it rather than sitting on an opaque slab: heavy blur + saturation
   for the refraction, a bright hairline along the top edge for the specular
   catch, a soft inner glow for thickness, and a moving glass "lens" behind
   the active tab. Falls back to the old solid bar where backdrop-filter is
   unsupported. */
.tabbar{
  position:fixed;z-index:60;display:flex;
  left:max(10px, env(safe-area-inset-left));
  right:max(10px, env(safe-area-inset-right));
  bottom:max(10px, env(safe-area-inset-bottom));
  padding:5px 5px;
  border-radius:26px;
  background:var(--glass-bg);
  border:1px solid var(--glass-edge);
  box-shadow:
    0 1px 0 0 var(--glass-spec) inset,
    0 -8px 22px -14px rgba(0,0,0,.5) inset,
    0 10px 34px -8px rgba(0,0,0,.45),
    0 2px 10px -3px rgba(0,0,0,.3);
  isolation:isolate;
}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tabbar{
    -webkit-backdrop-filter:blur(26px) saturate(200%) brightness(1.06);
    backdrop-filter:blur(26px) saturate(200%) brightness(1.06);
  }
}
:root{
  --glass-bg:rgba(252,252,253,.62);
  --glass-edge:rgba(255,255,255,.55);
  --glass-spec:rgba(255,255,255,.85);
  --glass-lens:rgba(255,255,255,.72);
}
[data-theme="dark"]{
  --glass-bg:rgba(28,28,32,.58);
  --glass-edge:rgba(255,255,255,.14);
  --glass-spec:rgba(255,255,255,.22);
  --glass-lens:rgba(255,255,255,.10);
}
@media(min-width:900px){.tabbar{display:none}}
.tab{
  position:relative;flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;
  padding:8px 2px 7px;color:var(--label2);font-size:10px;font-weight:500;letter-spacing:.005em;
  border-radius:21px;
  transition:color .22s var(--sp2, ease), transform .18s var(--sp, ease);
}
/* v64 — ONE lens that slides between tabs (per-tab fading looked static).
   Position and width are measured from the active tab, so it also handles
   the differing label widths. Overshoot easing gives it the iOS feel. */
.tab-lens{
  position:absolute;top:5px;bottom:5px;left:0;width:0;
  border-radius:21px;pointer-events:none;z-index:0;
  background:var(--glass-lens);
  box-shadow:0 1px 0 0 var(--glass-spec) inset, 0 1px 6px -2px rgba(0,0,0,.28);
  opacity:0;
  transition:transform .42s cubic-bezier(.34,1.42,.5,1),
             width .42s cubic-bezier(.34,1.42,.5,1),
             opacity .22s ease;
  will-change:transform,width;
}
.tab-lens.show{opacity:1}
.tab{z-index:1}
.tab.on{color:var(--tint)}
.tab svg{width:25px;height:25px}
.tab:active{transform:scale(.94)}
@media(prefers-reduced-motion:reduce){
  .tab,.tab-lens{transition:none}
}

/* ---------- inset grouped list ---------- */
.group{margin:0 0 22px}
.group>.ghead{
  color:var(--label2);font-size:13px;text-transform:uppercase;letter-spacing:.055em;
  font-weight:600;padding:0 16px 7px
}
.list{background:var(--bg-elev);border-radius:var(--radius-card);overflow:hidden;box-shadow:var(--shadow)}
.row{
  display:flex;align-items:center;gap:12px;padding:12px 16px;min-height:47px;
  position:relative;transition:background .14s;width:100%;text-align:left;color:var(--label)
}
.row+.row::before{
  content:"";position:absolute;top:0;left:16px;right:0;height:var(--hair);background:var(--sep-op)
}
.row.link:active{background:var(--fill)}
.row .rl{flex:1;min-width:0}
.row .rv{color:var(--label2);font-size:16px;text-align:right;flex-shrink:0;max-width:56%}
.row .chev{color:var(--label3);flex-shrink:0}
.ricon{
  width:29px;height:29px;border-radius:7px;display:grid;place-items:center;flex-shrink:0;
  background:var(--tint);color:#fff
}
[data-theme="dark"] .ricon{color:#062233}
/* v69 — Viv: the Follow rows should carry the real brand colours, same as the
   Instagram tile in the header. Both keep a white glyph, so they read at 16px. */
.ricon.ig{background:linear-gradient(45deg,#f9ce34 0%,#ee2a7b 50%,#6228d7 100%);color:#fff}
.ricon.fb{background:#1877F2;color:#fff}
[data-theme="dark"] .ricon.ig,[data-theme="dark"] .ricon.fb{color:#fff}

/* ---------- cards ---------- */
.card{
  background:var(--bg-elev);border-radius:var(--radius);overflow:hidden;
  box-shadow:var(--shadow);transition:transform .3s var(--sp),box-shadow .3s var(--sp)
}
a.card,button.card{display:block;color:var(--label);text-align:left;width:100%}
a.card:hover,button.card:hover{transform:translateY(-3px);box-shadow:var(--shadow-lg)}
a.card:active,button.card:active{transform:scale(.982)}
.card .pad{padding:15px 17px 17px}
.ratio{position:relative;width:100%;background:var(--fill);overflow:hidden}
.ratio>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .7s var(--sp)}
a.card:hover .ratio>img{transform:scale(1.045)}
.r-43{padding-top:75%}.r-11{padding-top:100%}.r-169{padding-top:56.25%}.r-32{padding-top:66.6%}.r-45{padding-top:125%}
/* v118 — the home "On the shelf" panels show a product packshot whole, on white, instead of cropping it. */
.card.shelf .ratio{background:#fff}.card.shelf .ratio>img{object-fit:contain;padding:7%;box-sizing:border-box}.card.shelf.fill .ratio>img{padding:0}

.grid{display:grid;gap:16px}
/* v23: grid items default to min-width:auto, so anything with a wide intrinsic
   size (the map iframes are 300px by spec) blows the track out past the
   container. This is the standard guard — it fixed a 22px overflow and 2px of
   horizontal page scroll on /contact at 360px. */
.grid>*{min-width:0}
/* v30 — Nick: "will it be better to swipe across?" On phones the home rows were
   a 2.7-screen wall of stacked cards. They now scroll sideways with snap, the
   way every big retailer does it. The next card deliberately peeks ~24% so the
   swipe is discoverable without an arrow or a hint. Desktop grids unchanged. */
@media(max-width:640px){
  .grid.swipe{
    display:flex;grid-template-columns:none;gap:12px;
    overflow-x:auto;-webkit-overflow-scrolling:touch;
    overscroll-behavior-x:contain;
    scroll-snap-type:x proximity;scroll-padding-left:var(--gut,20px);
    scrollbar-width:none;
    margin-left:calc(-1 * var(--gut,20px));margin-right:calc(-1 * var(--gut,20px));
    padding-left:var(--gut,20px);padding-right:var(--gut,20px);
    padding-top:6px;padding-bottom:6px;margin-top:-6px;margin-bottom:-2px
  }
  .grid.swipe::-webkit-scrollbar{display:none}
  .grid.swipe>*{flex:0 0 76%;scroll-snap-align:start}
  .grid.g5.swipe>*{flex:0 0 44%}
  .grid.g2.swipe>*{flex:0 0 84%}
}
/* v30 — Nick: the mobile footer was 20 links stacked into 1.5 screens. Two
   columns halves it; every link is kept (they matter for search once we launch,
   and they are the only deep links to individual collections). */
@media(max-width:640px){
  footer .cols>div:not(:first-child){column-count:2;column-gap:18px}
  footer .cols>div:not(:first-child) h3{column-span:all;margin-bottom:6px}
  footer a{padding:9px 0}
  footer .cols{gap:20px}
}
/* v24: the two big grids (559 tiles / 307 products) skip layout+paint for
   off-screen cards. Measured: shop render 499→~fast, filter-click 551ms and
   scroll chunk-paint spikes (218ms on a throttled phone) collapse, because
   only the ~15 visible cards actually render. 'auto' intrinsic size keeps the
   scrollbar honest once a card has been painted. Old Safari just ignores it. */
.tgrid>*{content-visibility:auto;contain-intrinsic-size:auto 300px}
#prodgrid>*{content-visibility:auto;contain-intrinsic-size:auto 280px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
.g4{grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
.dl-tiles{grid-template-columns:repeat(4,1fr)}
.dl-tiles .card .pad{height:100%;display:flex;flex-direction:column}
@media(max-width:640px){.dl-tiles{grid-template-columns:repeat(2,1fr)}.dl-tiles .card{aspect-ratio:1}.dl-tiles .t3{font-size:16px;line-height:1.2}}
.g5{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
@media(max-width:640px){
  .g3{grid-template-columns:1fr}
  .g2{grid-template-columns:1fr}
  .g4,.g5{grid-template-columns:repeat(2,1fr);gap:11px}
  .grid{gap:12px}
  .card .pad{padding:13px 14px 15px}
}
/* v93 — Nick: "it goes to this one item thumbnail, can you make it multiple so you can see
   heaps of items per screen". Two across on every phone (the old ≤380px rule made his phone
   a one-column list) and tighter cards, so a screen shows six or so instead of one. */
@media(max-width:640px){
  #prodgrid{gap:9px}
  #prodgrid .card .pad{padding:9px 10px 10px}
  #prodgrid .card .subhead{font-size:12.5px;line-height:1.25}
  #prodgrid .card .cap{font-size:12px}
  #prodgrid .card .cap.tint{display:none}
}
/* v23: the home rows have fixed item counts (6 collections, 10 products), so
   auto-fill left orphan cards stranded on a half-empty row at wide widths
   (4+2 and 8+2 at 2200px). Pinned column counts keep every row complete. */
@media(min-width:641px){.g3.row6{grid-template-columns:repeat(2,1fr)}}
@media(min-width:900px){.g3.row6{grid-template-columns:repeat(3,1fr)}}
@media(min-width:641px){.g5.row10{grid-template-columns:repeat(5,1fr)}}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  background:var(--tint);color:#fff;padding:13px 24px;border-radius:14px;
  font-size:16.5px;font-weight:600;letter-spacing:-.01em;
  transition:transform .14s var(--sp),filter .2s
}
[data-theme="dark"] .btn{color:#04231a}
.btn:active{transform:scale(.965)}
.btn:hover{filter:brightness(1.07)}
.btn.sec{background:var(--bg-elev2);color:var(--tint);box-shadow:inset 0 0 0 1px var(--sep-op)}
.btn.ghost{background:transparent;color:var(--tint);border:1.5px solid var(--tint)}
.btn.full{width:100%}
.btn.sm{padding:9px 16px;font-size:15px;border-radius:11px}
.btn-row{display:flex;gap:11px;flex-wrap:wrap}

/* ---------- segmented control ---------- */
.seg{
  display:inline-flex;background:var(--fill);border-radius:10px;padding:2px;gap:2px;
  max-width:100%;overflow-x:auto;scrollbar-width:none
}
.seg::-webkit-scrollbar{display:none}
.seg button{
  padding:6px 15px;border-radius:8px;font-size:14px;font-weight:600;letter-spacing:-.006em;
  color:var(--label);white-space:nowrap;transition:background .22s var(--sp2),color .2s
}
.seg button.on{background:var(--bg-elev);box-shadow:0 1px 3px rgba(0,0,0,.1)}
[data-theme="dark"] .seg button.on{background:var(--bg-elev2)}

/* ---------- chips ---------- */
.chips{display:flex;gap:8px;overflow-x:auto;padding:5px 0 6px;margin-top:-3px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.chips::-webkit-scrollbar{display:none}
/* v27: on desktop the category/brand chip rows WRAP instead of scrolling —
   Viv couldn't tell three categories were hiding past the right edge. Phones
   keep the horizontal scroll (vertical space is precious there); the sticky
   tiles filter bar keeps its scroll + arrows and is untouched. */
@media(min-width:901px){
  .chips{flex-wrap:wrap;overflow-x:visible;row-gap:8px;
    -webkit-mask-image:none!important;mask-image:none!important}
}
.chip{
  padding:7px 15px;border-radius:999px;background:var(--fill);
  font-size:14.5px;font-weight:500;white-space:nowrap;color:var(--label);
  transition:background .18s,color .18s,transform .12s var(--sp)
}
.chip.on{background:var(--tint);color:#fff}
[data-theme="dark"] .chip.on{color:#04231a}
.chip:active{transform:scale(.94)}

/* v101 — 40px minimum tap targets. Chips grow 5px taller; everything else keeps
   its drawn size and gains an invisible hit area (same trick as .icon-btn). */
.chip{display:inline-flex;align-items:center;min-height:40px}
.cchip,.tbtn{min-height:40px}
.crumbs a,.crumbs .backbtn,a.headline.tint,.bs-item,.foot a,.doclink,.ig-tile,.call-tile{position:relative}
/* v109 — invisible hit areas: every small text link and icon reaches 44 px tall on a phone */
.crumbs a::after,.crumbs .backbtn::after,a.headline.tint::after,.bs-item::after,.foot a::after,.doclink::after{content:"";position:absolute;left:0;right:0;top:-9px;bottom:-9px}
.icon-btn::after,.ig-tile::after,.call-tile::after{content:"";position:absolute;inset:0}
.hero-dots button::after{content:"";position:absolute;inset:0}
/* ---------- badge ---------- */
.badge{
  display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;
  background:var(--fill);font-size:12.5px;font-weight:600;color:var(--label2);letter-spacing:-.002em
}
/* v84 — home ticker: the four lines share one grid cell, so the box takes the
   height of the tallest line at the current width and never resizes (Nick: "keep
   the box size the same"). The live line fades and drifts up into place while the
   outgoing one drifts up and out — a crossfade, not a swap. */
.tk-stack{display:grid;align-items:center}
.ticker .tk{grid-area:1/1;display:flex;align-items:flex-start;gap:11px;opacity:0;visibility:hidden;
  transform:translateY(6px);filter:blur(6px);
  transition:opacity .36s ease,transform .36s var(--sp),filter .36s ease,visibility 0s linear .36s}
.ticker .note-dot{float:none;margin:6px 0 0}
.ticker .tkt{display:block;min-width:0}
/* the new line waits until the old one has all but gone, then resolves out of a blur —
   the way text changes in iOS. Glyphs never sit on top of each other. */
.ticker .tk.on{opacity:1;visibility:visible;transform:none;filter:none;
  transition:opacity .5s ease .16s,transform .55s var(--sp) .16s,filter .5s ease .16s,visibility 0s linear 0s}
.ticker .tk.out{transform:translateY(-6px)}
@media(prefers-reduced-motion:reduce){
  .ticker .tk,.ticker .tk.on{transition:opacity .2s linear,visibility 0s linear .2s;transform:none;filter:none}
  .ticker .tk.on{transition-delay:0s}
  .ticker .tk.out{transform:none}
}
/* v84 — home hero: both stores' open/closed pills sit at the top of the photo, frosted,
   like the single pill did before v81 (Nick: "on the tile image as you did before, but up
   the top"). Left edge lines up with the headline below. */
.hero-status{position:absolute;z-index:2;display:flex;flex-wrap:wrap;gap:8px;
  top:calc(env(safe-area-inset-top) + var(--navh) + var(--navi,0px) + 14px);
  left:max(var(--gut,20px),calc((100% - var(--maxw,1120px))/2 + var(--gut,20px)));
  right:var(--gut,20px)}
.hero-status .badge{text-decoration:none;white-space:nowrap}
.hero-status .badge .st{display:inline-flex;align-items:center;gap:4px}
@media(max-width:640px){
  .hero-status{display:grid;grid-template-columns:max-content;gap:7px}
  .hero-status .badge{justify-content:flex-start}
  /* v86 — Nick: "the Carrum Downs font looks smaller than Coburg" (it was the same
     size; the longer line filled its pill and read smaller). The two pills now share
     one column grid, so dot, store name, separator and status start on the same line
     in both rows and nothing has to be eyeballed. */
  @supports (grid-template-columns:subgrid){
    .hero-status{grid-template-columns:max-content max-content max-content max-content;column-gap:5px}
    .hero-status .badge{display:grid;grid-template-columns:subgrid;grid-column:1/-1;align-items:center;justify-items:start}
  }
}
.badge.ok{background:var(--tint-soft);color:var(--tint)}
.badge.live{background:rgba(52,199,89,.16);color:#1D7433}
[data-theme="dark"] .badge.live{background:rgba(48,209,88,.2);color:#30D158}
.badge.shut{background:rgba(255,59,48,.14);color:#C00012}
[data-theme="dark"] .badge.shut{background:rgba(255,69,58,.16);color:#FF6A61}
.badge.soon{background:rgba(255,159,10,.16);color:#985100}   /* v90 — opening within the hour */
[data-theme="dark"] .badge.soon{background:rgba(255,159,10,.2);color:#FF9F0A}
.dot{width:6px;height:6px;border-radius:50%;background:currentColor}

/* ---------- hero ---------- */
.hero{
  position:relative;border-radius:26px;overflow:hidden;margin-top:14px;
  min-height:clamp(430px,62vh,600px);display:flex;align-items:flex-end;
  box-shadow:var(--shadow-lg)
}
.hero-bg{position:absolute;inset:0}
.hero-bg img{width:100%;height:100%;object-fit:cover}
.hero-bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.42) 0%,rgba(0,0,0,.12) 34%,rgba(0,0,0,.30) 62%,rgba(0,0,0,.80) 100%)
}
.hero-in{position:relative;padding:30px 26px 30px;color:#fff;width:100%}
.hero h1{font-size:clamp(34px,6.6vw,58px);line-height:1.03;font-weight:700;letter-spacing:-.033em;margin:0 0 12px;text-shadow:0 2px 22px rgba(0,0,0,.4)}
.hero p{font-size:clamp(16px,2.1vw,19px);margin:0 0 22px;max-width:520px;color:rgba(255,255,255,.94);text-shadow:0 1px 14px rgba(0,0,0,.5)}
.hero .btn{background:#fff;color:#111}
.hero .btn.ghost{background:rgba(255,255,255,.14);color:#fff;border-color:rgba(255,255,255,.45);
  -webkit-backdrop-filter:blur(18px) saturate(180%);backdrop-filter:blur(18px) saturate(180%);
  box-shadow:0 1px 0 0 rgba(255,255,255,.35) inset,0 8px 22px -10px rgba(0,0,0,.5)}   /* v84 — glass */
/* badges sitting on photography get a frosted treatment, never a colour fill */
.hero .badge{
  background:rgba(255,255,255,.16);color:#fff;
  -webkit-backdrop-filter:blur(18px) saturate(180%);backdrop-filter:blur(18px) saturate(180%);
  box-shadow:0 1px 0 0 rgba(255,255,255,.5) inset,0 0 0 .5px rgba(255,255,255,.34) inset,0 8px 22px -10px rgba(0,0,0,.55);
  padding:6px 13px 6px 11px;font-size:13.5px
}
[data-theme="dark"] .hero .badge.live,[data-theme="dark"] .hero .badge.shut{background:rgba(255,255,255,.16);color:#fff}
.hero .badge .dot{background:#30D158;box-shadow:0 0 7px #30D158}
.hero .badge.soon .dot{background:#FFD426;box-shadow:0 0 7px #FFD426}
.hero .badge.shut .dot{background:#FF453A;box-shadow:0 0 7px #FF453A}
/* v90 — the state word glows in the marker's colour (Nick) */
.hero-status .badge .stw{font-weight:700}
.hero-status .badge.live .stw{color:#3DDC6A;text-shadow:0 0 6px rgba(48,209,88,.9),0 0 16px rgba(48,209,88,.5)}
.hero-status .badge.soon .stw{color:#FFD94A;text-shadow:0 0 6px rgba(255,212,38,.9),0 0 16px rgba(255,212,38,.5)}
.hero-status .badge.shut .stw{color:#FF7A70;text-shadow:0 0 6px rgba(255,69,58,.9),0 0 16px rgba(255,69,58,.5)}
[data-theme="dark"] .hero .badge.live,[data-theme="dark"] .hero .badge.shut,[data-theme="dark"] .hero .badge.soon{background:rgba(255,255,255,.16);color:#fff}
/* v29 — Nick's catch: on phones the two CTAs were full-width slabs, so the
   content block ate 75-92% of the hero and the photograph (the actual product
   for a tile shop) was reduced to a strip. Buttons are now compact pills that
   sit side by side; the hero also gets more height on mobile. */
@media(max-width:520px){
  .hero .btn-row{gap:8px;flex-wrap:wrap}
  .hero .btn{flex:0 1 auto;justify-content:center;
    font-size:15px;padding:12px 16px;letter-spacing:-.012em}
  .hero .btn svg{width:16px;height:16px}
  .hero p{margin-bottom:16px}
  .hero-in{padding-bottom:34px}
}
/* narrow phones: shave enough to keep both CTAs on ONE row */
@media(max-width:410px){
  .hero .btn-row{gap:6px}
  .hero .btn{font-size:14.5px;padding:12px 12px}
}
/* very small/old phones (320px): drop the icon so both CTAs still share a row */
@media(max-width:345px){
  .hero .btn{font-size:13.5px;padding:11px 10px}
  .hero .btn svg{display:none}
}
/* v24: the dots were 7px touch targets. The button is now a 28px invisible
   hit box; the visible dot is a ::before, so the look is unchanged. */
.hero-dots{position:absolute;bottom:0;right:10px;display:flex;z-index:2}
.hero-dots button{position:relative;width:44px;height:44px;margin:0 -4px;display:grid;place-items:center;background:none;border:0;padding:0}
.hero-dots button::before{content:"";width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.42);transition:all .35s var(--sp)}
.hero-dots button.on::before{background:#fff;width:22px;border-radius:4px}

/* v23: full-bleed hero — edge to edge, like the live site.
   Sits OUTSIDE .wrap in the markup so it fills main without 100vw
   (which would overshoot by the scrollbar width and cause h-scroll).
   The inner content re-aligns to the container so the headline lines
   up with everything below it. */
.hero-bleed{
  border-radius:0;margin-top:0;box-shadow:none;
  min-height:clamp(430px,64vh,720px)
}
.hero-bleed .hero-in{
  max-width:var(--maxw,1120px);margin:0 auto;
  padding:34px var(--gut,20px) 40px
}
.hero-bleed .hero-dots{
  right:max(8px,calc((100% - var(--maxw,1120px))/2 + var(--gut,20px) - 14px));
  bottom:2px
}
/* secondary bleed hero (collection pages): shorter strip, same alignment */
.hero-bleed.hero-strip{min-height:clamp(260px,40vh,460px);margin-top:14px}
.hero-bleed.hero-strip .hero-in{padding:26px var(--gut,20px) 28px}
@media(max-width:640px){
  .hero-bleed{min-height:clamp(470px,66vh,600px)}
  .hero-bleed.hero-strip{min-height:clamp(220px,34vh,300px)}
}

/* ---------- swatches ---------- */
.sw-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:13px}
.sw{
  border-radius:14px;overflow:hidden;background:var(--bg-elev);
  box-shadow:var(--shadow);transition:transform .28s var(--sp),box-shadow .28s var(--sp);text-align:center
}
.sw:hover{transform:translateY(-3px) scale(1.02);box-shadow:var(--shadow-lg)}
.sw:active{transform:scale(.96)}
.sw .ratio{padding-top:100%}
.sw .nm{padding:8px 6px 10px;font-size:12.5px;font-weight:600;letter-spacing:-.004em;color:var(--label)}

/* ---------- spec table ---------- */
.spec{background:var(--bg-elev);border-radius:var(--radius-card);overflow:hidden;box-shadow:var(--shadow)}
.spec .sr{display:flex;padding:11px 16px;gap:14px;position:relative;align-items:flex-start}
.spec .sr+.sr::before{content:"";position:absolute;top:0;left:16px;right:0;height:var(--hair);background:var(--sep-op)}
.spec .sk{color:var(--label2);font-size:15.5px;width:112px;flex-shrink:0}
.spec .sv{font-size:15.5px;font-weight:500;flex:1;text-align:right}

/* ---------- sheet / modal ---------- */
.backdrop{
  position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:90;opacity:0;pointer-events:none;
  transition:opacity .38s var(--sp);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)
}
.backdrop.on{opacity:1;pointer-events:auto}
.sheet{
  position:fixed;left:0;right:0;bottom:0;z-index:95;background:var(--bg);
  border-radius:14px 14px 0 0;max-height:92vh;overflow-y:auto;overscroll-behavior:contain;
  transform:translateY(101%);transition:transform .45s var(--sp);
  padding-bottom:env(safe-area-inset-bottom);box-shadow:0 -8px 40px rgba(0,0,0,.24);
  pointer-events:none
}
.sheet.on{transform:translateY(0);pointer-events:auto}
@media(min-width:760px){
  .sheet{left:50%;right:auto;bottom:auto;top:50%;width:min(660px,92vw);border-radius:18px;
    transform:translate(-50%,-46%) scale(.96);opacity:0;max-height:88vh}
  .sheet.on{transform:translate(-50%,-50%) scale(1);opacity:1}
}
.grabber{width:36px;height:5px;border-radius:3px;background:var(--label3);margin:8px auto 0}
.sheet-head{
  position:sticky;top:0;z-index:2;background:var(--glass-bg);
  -webkit-backdrop-filter:blur(26px) saturate(200%) brightness(1.06);backdrop-filter:blur(26px) saturate(200%) brightness(1.06);
  box-shadow:0 1px 0 0 var(--glass-spec) inset;   /* v84 — glass */
  display:flex;align-items:center;gap:12px;padding:6px 13px 6px 18px;border-bottom:1px solid var(--glass-edge)
}
.sheet-body{padding:18px}

/* ---------- search ---------- */
.searchfield{
  display:flex;align-items:center;gap:8px;background:var(--fill);
  border-radius:11px;padding:0 13px;color:var(--label2);width:100%
}
/* v24: vertical padding lives on the input, not the wrapper — same look, but
   the tappable input is now 48px tall instead of 22px */
.searchfield input{
  border:0;background:none;outline:0;flex:1;font-size:17px;color:var(--label);
  font-family:inherit;letter-spacing:-.01em;min-width:0;padding:13px 0
}
.searchfield input::placeholder{color:var(--label2)}

/* ---------- misc ---------- */
.divider{height:var(--hair);background:var(--sep-op);margin:26px 0}
.kv{display:flex;justify-content:space-between;gap:14px;padding:5px 0;font-size:15.5px}
.note{
  background:var(--fill);border-radius:14px;padding:15px 17px;font-size:15.5px;
  color:var(--label)   /* v86 grey, not green · v88 — Nick again in day mode: the green accent bar goes too; only the dot stays green */
}
/* v34: two-line notes (stock guarantee) — icon beside the block, not above it */
.note>svg{float:left;margin:2px 9px 0 0}
.note b{display:block;margin-bottom:1px}

/* v63 — the hours rows carried an inline 2px side padding, so on iOS the
   times sat hard against the card edge and read as clipped. Real gutters,
   and the value may now shrink instead of overflowing. */
.row.hrow{padding:10px 14px}
.row.hrow .rl{flex:1 1 auto;min-width:0}
.row.hrow .rv{flex:0 1 auto;min-width:0;max-width:none;white-space:nowrap}
@media(max-width:420px){
  .row.hrow{padding:10px 12px;gap:10px}
  .row.hrow .rl.body{font-size:16px}
  .row.hrow .rv{font-size:15px}
}

/* v63 — stock guarantee read as a flat white dot. Lit green marker with a
   soft halo, and the heading gets a touch more presence. */
.note-dot{
  float:left;width:11px;height:11px;border-radius:50%;margin:6px 11px 0 0;
  background:var(--tint);flex:0 0 auto;
  box-shadow:0 0 0 3px var(--tint-soft), 0 0 10px 1px var(--tint);
  animation:notePulse 2.4s var(--sp2, ease-in-out) infinite
}
@keyframes notePulse{
  0%,100%{box-shadow:0 0 0 3px var(--tint-soft), 0 0 8px 0 var(--tint)}
  50%    {box-shadow:0 0 0 5px var(--tint-soft), 0 0 14px 2px var(--tint)}
}
@media(prefers-reduced-motion:reduce){.note-dot{animation:none}}
.note b{font-weight:700;letter-spacing:-.012em;font-size:16px}
/* v85 — the bold heading is already a block, so the <br> after it made a blank line
   inside every note (visible on the shop pages' stock guarantee). */
.note b+br{display:none}
/* v34: tint-on-tint-soft is legible but reads as body text — underline so an
   inline link inside a note is obviously a link. */
.note a{text-decoration:underline;text-underline-offset:2px;font-weight:600;color:var(--tint-ink)}
.prose p{margin:0 0 15px;font-size:17px;line-height:1.6}
/* v116 — a long unbroken run (a colour-code list, an email address in brackets) in supplier copy must wrap
   rather than push a 390 px phone page sideways (KERACOLOR FF, 10 Sep sweep). Same rule .lg-title and
   .tz-specs dd already carry. */
.prose{overflow-wrap:anywhere;min-width:0}
.prose p:last-child{margin-bottom:0}.doclinks{display:flex;flex-wrap:wrap;gap:10px 20px;margin:20px 0 0}.doclink{font-size:15px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.ratio>a{position:absolute;inset:0;display:block}.ratio>a>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.prose h3,.prose h2{font-size:20px;font-weight:600;letter-spacing:-.018em;margin:26px 0 9px}

/* v34 — real customer reviews. Carried over verbatim from the reviews published
   on wallboulevard.com.au. No star graphics and no aggregate rating: we can't
   verify either until Luke's Google Business Profile is in hand, and inventing
   a rating on a review card is the kind of thing that gets a listing pulled. */
.rev{display:flex;flex-direction:column;height:100%;padding:19px 19px 17px}
.rev .qt{font-size:15.5px;line-height:1.62;color:var(--label);margin:0 0 14px}
.rev .who{display:flex;align-items:center;gap:10px;margin-top:auto}
.rev .av{width:32px;height:32px;border-radius:50%;background:var(--tint-soft);color:var(--tint);
  display:grid;place-items:center;font-size:12.5px;font-weight:650;flex:0 0 auto;letter-spacing:.01em}
.rev .nm{font-size:14.5px;font-weight:600;letter-spacing:-.007em;color:var(--ink)}
.rev .role{font-size:12px;color:var(--label2);margin-top:1px}
/* home row only: even the cards out so a 70-word review and a 4-word one sit level */
/* max-height belt to the line-clamp braces: as a flex item with -webkit-box
   display, the clamp let an 8th line bleed a few pixels below the fold. The
   attribution row is pinned by .who{margin-top:auto}, so .qt must NOT grow. */
.rev.clip .qt{display:-webkit-box;-webkit-line-clamp:7;-webkit-box-orient:vertical;
  overflow:hidden;flex:0 0 auto;max-height:calc(7 * 1.62em)}
/* the /reviews page: a masonry wall, because the lengths vary wildly */
.revwall{column-count:3;column-gap:16px}
.revwall>*{break-inside:avoid;width:100%;margin:0 0 16px;display:inline-block;vertical-align:top}
@media(max-width:1000px){.revwall{column-count:2}}
@media(max-width:640px){.revwall{column-count:1}}

/* v34 — tile guide. The ~2,000 words of educational copy that sat as a wall of
   text at the bottom of the old home page. A dedicated page ranks better than a
   blob under a homepage, and the home page gets its design back. Sticky contents
   rail on desktop, a chip row on phones — no in-page anchors, because #fragments
   fight the hash router. Scrolling is done in JS off data-scroll. */
.gd-wrap{display:grid;grid-template-columns:minmax(0,1fr);margin-top:26px;max-width:1020px}
@media(min-width:960px){.gd-wrap{grid-template-columns:224px minmax(0,1fr);gap:46px}}
.gd-toc{display:none}
@media(min-width:960px){
  .gd-toc{display:block;position:sticky;align-self:start;
    top:calc(var(--navh) + var(--navi,0px) + 22px);max-height:calc(100vh - var(--navh) - var(--navi,0px) - 54px);overflow:auto;
    scrollbar-width:none;border-left:var(--hair) solid var(--sep);padding-left:15px}
  .gd-toc::-webkit-scrollbar{display:none}
}
.gd-link{display:block;width:100%;text-align:left;padding:6px 0;border:0;background:none;cursor:pointer;
  font:inherit;font-size:13.5px;line-height:1.35;letter-spacing:-.004em;color:var(--label2)}
.gd-link:hover{color:var(--tint)}
.gd-link.on{color:var(--tint);font-weight:640}
.gd-chips{margin-bottom:6px}
@media(min-width:960px){.gd-chips{display:none}}
.gd-sec{margin-top:34px;scroll-margin-top:calc(var(--navh) + var(--navi,0px) + 22px)}
.gd-sec:first-child{margin-top:26px}

/* skeleton shimmer */
.shim{background:linear-gradient(100deg,var(--fill) 30%,var(--fill2) 50%,var(--fill) 70%);
  background-size:220% 100%;animation:sh 1.4s infinite}
@keyframes sh{to{background-position:-220% 0}}

/* page transition */
.view{animation:vin .42s var(--sp) both}
@keyframes vin{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
.rise{opacity:0;transform:translateY(16px)}
.rise.in{opacity:1;transform:none;transition:opacity .62s var(--sp),transform .62s var(--sp)}

/* footer */
footer{background:var(--bg-elev);margin-top:56px;padding:38px 0 34px;border-top:var(--hair) solid var(--sep)}
footer .cols{display:grid;gap:26px;grid-template-columns:repeat(auto-fit,minmax(165px,1fr))}
/* v23: give the store/logo column the room it actually needs so the logo
   stays large instead of shrinking to fit a quarter-width track */
@media(max-width:900px){footer .cols>div:first-child{grid-column:1/-1;margin-bottom:4px}}
@media(min-width:901px){footer .cols{grid-template-columns:minmax(300px,1.6fr) repeat(3,minmax(150px,1fr))}}
/* v72 — these were h4 with no h3 above them on nearly every page, which
   breaks the heading outline a screen reader navigates by. Moved to h3;
   this selector MUST move with them or the footer loses its styling. */
footer h2,footer h3{font-size:13px;text-transform:uppercase;letter-spacing:.055em;color:var(--label2);margin:0 0 11px;font-weight:600}
footer a{display:block;color:var(--label);font-size:15px;padding:9px 0;transition:color .16s}   /* v101 — 40px tap height */
footer a:hover{color:var(--tint)}

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

.fi{width:100%;background:var(--fill);border:0;border-radius:11px;padding:12px 14px;font:inherit;
  font-size:16.5px;color:var(--label);outline:0;font-family:inherit;letter-spacing:-.01em}
.fi::placeholder{color:var(--label2)}
.fi:focus{box-shadow:0 0 0 2.5px var(--tint)}
textarea.fi{resize:vertical;min-height:96px}

/* ===== native tile selector ===== */
.tsel-bar{position:sticky;top:calc(var(--navh) + var(--navi,0px));z-index:40;background:var(--glass-bg);transition:top .32s var(--sp2);
  -webkit-backdrop-filter:blur(26px) saturate(200%) brightness(1.06);backdrop-filter:blur(26px) saturate(200%) brightness(1.06);
  border-bottom:1px solid var(--glass-edge);
  box-shadow:0 1px 0 0 var(--glass-spec) inset,0 10px 28px -14px rgba(0,0,0,.28);   /* v84 — glass */
  margin:14px calc(-1 * var(--gut,20px)) 0;padding:11px var(--gut,20px) 10px}
.tsel-scroll{display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;padding:5px 0 5px;margin:-4px 0 -2px}
.tsel-scroll::-webkit-scrollbar{display:none}

/* horizontal chip rows: fade the edges so a clipped chip reads as "scrolls"
   rather than "broken", and let chips run out to the screen edge on phones */
.tsel-scroll,.chips{
  --fade-l:0px; --fade-r:30px;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 var(--fade-l),#000 calc(100% - var(--fade-r)),transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 var(--fade-l),#000 calc(100% - var(--fade-r)),transparent 100%);
}
.tsel-scroll.at-start,.chips.at-start{--fade-l:0px}
.tsel-scroll:not(.at-start),.chips:not(.at-start){--fade-l:26px}
.tsel-scroll.at-end,.chips.at-end{--fade-r:0px}
.tsel-scroll.at-start.at-end,.chips.at-start.at-end{-webkit-mask-image:none;mask-image:none}
@media(max-width:900px){
  .tsel-bar .tsel-scroll{margin-left:-20px;margin-right:-20px;padding-left:20px;padding-right:20px;
    scroll-padding-left:20px}
  .wrap > .chips,.wrap .chips{margin-left:-20px;margin-right:-20px;padding-left:20px;padding-right:20px;
    scroll-padding-left:20px}
}
.cchip{flex:0 0 auto;scroll-snap-align:start;display:inline-flex;align-items:center;gap:7px;
  background:var(--fill);color:var(--label);border:0;
  border-radius:999px;padding:7px 14px;font-size:14px;font-weight:500;white-space:nowrap;
  cursor:pointer;transition:background .18s,color .18s,transform .14s var(--sp),opacity .18s;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation}
.cchip:active{transform:scale(.93)}
.cchip.on{background:var(--tint);color:#fff}
.cchip.on .qty{opacity:.92}
.cchip.on i{box-shadow:inset 0 0 0 1px rgba(255,255,255,.55)}
/* v46 — dark mode turns --tint into a bright mint, and white on it falls to
   1.98:1 (the count inside, at 80%, to 1.72:1). Same treatment the sheet
   already gives .btn, .call-btn, .ricon and .brand .mark on a tint background. */
[data-theme="dark"] .cchip.on{color:#04231a}
[data-theme="dark"] .cchip.on .qty{opacity:.92}
[data-theme="dark"] .cchip.on i{box-shadow:inset 0 0 0 1px rgba(0,0,0,.4)}
.cchip.off{opacity:.3;pointer-events:none}
.cchip i{width:15px;height:15px;border-radius:50%;background:var(--d);
  box-shadow:inset 0 0 0 1px rgba(128,128,128,.42);flex:0 0 auto}
.cchip .qty{font-size:12px;opacity:.62;font-variant-numeric:tabular-nums}
.tsel-sups{margin-top:8px}
.tsel-sups .cchip.sup{font-size:12.5px;padding:6px 11px}
/* v74 — the tiles search box. Slightly tighter than the standard .searchfield
   because this bar is sticky and every pixel of it is content the customer
   cannot see; 44px still clears the 44px tap-target guideline. */
.tsel-search{margin-top:9px;max-width:520px}
.tsel-search input{padding:11px 0;font-size:16px}
.tsel-row2{display:flex;align-items:center;gap:9px;margin-top:10px}
.tbtn{display:inline-flex;align-items:center;gap:6px;background:var(--fill);color:var(--label);
  border:0;border-radius:999px;padding:7px 14px;font-size:14px;font-weight:500;cursor:pointer;
  -webkit-tap-highlight-color:transparent;transition:background .18s,color .18s,transform .14s var(--sp)}
.tbtn:active{transform:scale(.93)}
.tbtn.hot{background:var(--tint);color:#fff}
[data-theme="dark"] .tbtn.hot{color:#04231a}
.tbtn .badge{min-width:18px;height:18px;border-radius:999px;background:#fff;
  color:var(--tint);font-size:12px;font-weight:700;display:grid;place-items:center;padding:0 5px;
  font-variant-numeric:tabular-nums}
[data-theme="dark"] .tbtn .badge{background:#04231a;color:#fff}
.tsel-count{margin-left:auto;font-size:13px;color:var(--label2);font-variant-numeric:tabular-nums}
.tgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-top:18px}
@media(min-width:620px){.tgrid{grid-template-columns:repeat(3,1fr);gap:14px}}
@media(min-width:900px){.tgrid{grid-template-columns:repeat(4,1fr);gap:16px}}
@media(min-width:1240px){.tgrid{grid-template-columns:repeat(5,1fr)}}
@media(min-width:1500px){.tgrid{grid-template-columns:repeat(6,1fr)}}
@media(min-width:2200px){.tgrid{grid-template-columns:repeat(7,1fr)}}
.tcard{display:flex;flex-direction:column;width:100%;text-align:left;background:var(--bg-elev);
  border:0;border-radius:var(--radius);overflow:hidden;cursor:pointer;padding:0;color:var(--ink);
  box-shadow:var(--shadow);transition:transform .26s var(--sp),box-shadow .26s var(--sp);
  -webkit-tap-highlight-color:transparent;animation:tin .36s var(--sp) both}
@keyframes tin{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
.tcard:active{transform:scale(.965)}
@media(hover:hover){.tcard:hover{transform:translateY(-3px);box-shadow:var(--shadow-lg)}}
.tcard .ph{display:block;position:relative;width:100%;aspect-ratio:1/1;overflow:hidden;background:var(--fill2)}
.tcard .ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.chip .qty{font-size:12px;opacity:.62;font-variant-numeric:tabular-nums;margin-left:1px}
.chip.on .qty{opacity:.92}
.crumbs{display:flex;align-items:center;flex-wrap:wrap;gap:2px;font-size:13px;margin:0 0 10px;
  color:var(--label2);line-height:1.5}
.crumbs a,.crumbs span{display:inline-flex;align-items:center;padding:5px 0;border-radius:6px}
.crumbs a{color:var(--label2);text-decoration:none;padding:12px 0;margin:-7px 0;min-height:44px}
.crumbs a:hover{color:var(--ink);text-decoration:underline}
.crumbs .sep{opacity:.45;padding:0 6px;flex:0 0 auto}
.crumbs .cur{color:var(--ink);font-weight:540}
.crumbs .cur{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:640px){
  .crumbs{font-size:12.5px}
  /* the page title right below already names the current page */
  .crumbs .cur,.crumbs > .sep:nth-last-child(2){display:none}
}
.tcard .slipbadge{position:absolute;right:7px;bottom:7px;z-index:2;font-size:12px;font-weight:640;
  letter-spacing:.02em;padding:2.5px 6px;border-radius:6px;background:rgba(20,20,22,.62);color:#fff;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);line-height:1.25}
.tcard .tmeta{display:block;padding:10px 12px 13px}
.tcard .nm2{display:block;font-size:14.5px;font-weight:550;letter-spacing:-.012em;line-height:1.26;
  color:var(--ink)}
.tcard .rg{display:block;font-size:12.5px;color:var(--label2);margin-top:3px}
.tsel-empty{text-align:center;padding:54px 20px}
.tmore{text-align:center;padding:26px 20px 4px;display:none}
.tmore.on{display:block}
.fsheet-sec{margin-bottom:20px}
.fsheet-sec h5{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--label2);
  margin:0 0 10px;font-weight:600}
.fwrap{display:flex;flex-wrap:wrap;gap:8px}


.mapbox{margin-top:16px;border-radius:14px;overflow:hidden;background:var(--fill2);
  box-shadow:var(--shadow)}
.mapbox iframe{display:block;width:100%;min-width:0;height:230px;border:0}
@media(min-width:900px){.mapbox iframe{height:260px}}


.tsel-scrollwrap{position:relative;display:flex;align-items:center;gap:6px}
.tsel-scrollwrap .tsel-scroll{flex:1;min-width:0}
.tsel-arrow{display:none;flex:0 0 auto;width:30px;height:30px;border-radius:999px;border:0;
  background:var(--fill);color:var(--label);cursor:pointer;place-items:center;
  transition:background .18s,opacity .18s,transform .14s var(--sp)}
.tsel-arrow:active{transform:scale(.9)}
.tsel-arrow.left svg{transform:rotate(180deg)}
.tsel-arrow[disabled]{opacity:.28;pointer-events:none}
.tsel-arrow.gone{display:none!important}
@media(min-width:900px) and (hover:hover){.tsel-arrow{display:grid}}


/* ===== editorial (About) ===== */
:root{--serif:'Montserrat',-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;--navh:64px;--navi:0px}  /* v84 --navi = the header's inset from the top edge; v85 = 0 (square, edge to edge) */
@media(max-width:900px){:root{--navh:58px}}

/* ===== v23: wide-screen scaling =====
   The whole site used to be pinned at 1120px, which letterboxed large monitors
   (49% dead space at 2200px). Container now steps up; prose keeps its own
   narrow max-widths so line length stays readable. */
:root{--maxw:1120px;--gut:20px}
@media(min-width:1500px){:root{--maxw:1280px;--gut:24px}}
@media(min-width:1800px){:root{--maxw:1400px;--gut:28px}}
@media(min-width:2200px){:root{--maxw:1520px;--gut:32px}}
/* v23: the About article's blocks top out at 1020px, so on a wide monitor the
   whole column hugged the left of a 1520px container with 436px dead to the
   right. Capping this page's container centres the column and keeps every
   block's left edge aligned. */
.ed-page{max-width:min(var(--maxw,1120px),1060px)}
.ed-kicker{font-size:12px;font-weight:640;letter-spacing:.16em;text-transform:uppercase;color:var(--tint)}
.ed-title{font-family:var(--serif);font-weight:600;font-size:clamp(40px,6.4vw,68px);line-height:1.02;letter-spacing:-.014em;margin:12px 0 0;color:var(--ink)}
.ed-stand{font-family:var(--serif);font-style:italic;font-size:clamp(19px,2.3vw,24px);line-height:1.5;color:var(--label2);margin:20px 0 0;max-width:660px}
.ed-rule{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;margin-top:26px;padding:13px 0;border-top:2px solid var(--ink);border-bottom:var(--hair) solid var(--sep);font-size:13px;color:var(--label2);letter-spacing:.02em}
.ed-rule b{color:var(--ink);font-weight:600}
.ed-body{font-family:var(--serif);font-size:18px;line-height:1.75;color:var(--ink)}
.ed-body p{margin:0 0 1.15em}
/* v32: drop cap removed — at 76px in a narrow column it read as a typo, not a flourish */
.ed-h{font-family:var(--serif);font-weight:600;font-size:25px;letter-spacing:-.01em;line-height:1.2;margin:0 0 14px;color:var(--ink)}
.ed-quote{font-family:var(--serif);font-size:clamp(23px,2.9vw,31px);font-style:italic;line-height:1.4;color:var(--ink);border-left:3px solid var(--tint);padding:4px 0 4px 24px;margin:38px 0}
.ed-figure{margin:38px 0}
.ed-figure img{width:100%;display:block;border-radius:6px;aspect-ratio:21/9;object-fit:cover}
.ed-cap{font-size:12.5px;color:var(--label2);margin-top:9px;letter-spacing:.02em}
.ed-stats{display:grid;grid-template-columns:repeat(4,1fr);border-top:2px solid var(--ink);margin:40px 0}
.ed-stat{padding:18px 16px 20px;border-right:var(--hair) solid var(--sep)}
.ed-stat:last-child{border-right:0}
.ed-stat .n{font-family:var(--serif);font-weight:600;font-size:clamp(26px,3.4vw,40px);letter-spacing:-.015em;color:var(--ink)}
.ed-stat .n-map{display:flex;align-items:flex-end;height:clamp(46px,5.6vw,64px)}
.ed-stat .n-map svg{height:100%;width:auto}
.ed-stat .l{font-size:12px;font-weight:620;letter-spacing:.1em;text-transform:uppercase;color:var(--label2);margin-top:5px}
.ed-grid2{display:grid;grid-template-columns:1fr 1fr;gap:44px;margin:8px 0 6px}
.ed-tl{list-style:none;margin:0;padding:0 0 0 24px;border-left:1px solid var(--sep)}
.ed-tl li{position:relative;padding:0 0 20px 18px}
.ed-tl li::before{content:'';position:absolute;left:-28px;top:9px;width:7px;height:7px;border-radius:50%;background:var(--tint)}
.ed-tl .y{font-family:var(--serif);font-weight:600;font-size:19px;color:var(--ink)}
.ed-tl .e{font-size:14.5px;line-height:1.55;color:var(--label2);margin-top:2px}
.ed-visit{border-top:2px solid var(--ink);margin-top:44px;padding-top:8px;display:grid;grid-template-columns:1fr 1fr;gap:34px}
.ed-store{padding-top:14px}
.ed-store .sn{font-family:var(--serif);font-weight:600;font-size:21px;color:var(--ink)}
.ed-store .sa{font-size:14px;color:var(--label2);margin-top:5px;line-height:1.5}
@media(max-width:760px){
  .ed-grid2,.ed-visit{grid-template-columns:1fr;gap:28px}
  .ed-stats{grid-template-columns:1fr 1fr}
  .ed-stat:nth-child(2){border-right:0}
  .ed-figure img{aspect-ratio:16/10}
}


/* two-store nav pills */
.call-duo{display:none;align-items:stretch;gap:7px}
.cd-store{display:flex;flex-direction:column;justify-content:center;gap:1px;
  background:var(--fill);border-radius:12px;padding:5px 13px 6px;
  transition:background .18s,transform .14s var(--sp)}
.cd-store:hover{background:var(--fill2)}
.cd-store:active{transform:scale(.95)}
.cd-l{display:flex;align-items:center;gap:5px;font-size:10px;font-weight:640;
  letter-spacing:.07em;text-transform:uppercase;color:var(--label2);white-space:nowrap}
.cd-n{font-size:12.5px;font-weight:600;color:var(--ink);letter-spacing:-.006em;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.cd-dot{width:6px;height:6px;border-radius:50%;background:#98989d;flex:0 0 auto}
.cd-dot.live{background:#30d158}
.cd-dot.shut{background:#ff453a}



/* instagram nav tile */
.ig-tile{width:44px;height:44px;border-radius:9px;flex:0 0 auto;display:grid;place-items:center;color:#fff;isolation:isolate;
  background:none;
  transition:transform .14s var(--sp),filter .18s}
.ig-tile:hover{filter:brightness(1.12)}
.ig-tile:active{transform:scale(.9)}


.call-tile{width:44px;height:44px;border-radius:9px;flex:0 0 auto;display:grid;place-items:center;isolation:isolate;
  color:#fff;background:none;transition:transform .14s var(--sp),filter .18s}  /* v94 — Nick: the call button green, like the phone app on iOS and Android */
.call-tile:hover{filter:brightness(1.1)}
.call-tile:active{transform:scale(.9)}


.brandlogo{display:block;height:52px;aspect-ratio:334/53;width:auto;
  background:url(/images/wb-logo-h.svg) no-repeat center/contain}
/* v63 — iOS Safari renders NOTHING for an empty element sized only by
   aspect-ratio + width:auto inside a flex row: it resolves the width to 0.
   Chrome derives it, Safari does not, so the wordmark simply vanished on
   iPhone. Give width an explicit value at every height; aspect-ratio stays
   as a progressive enhancement, max-width:100% keeps the v23 shrink. */
.brandlogo{width:328px;max-width:100%}
@supports ((-webkit-mask-image:url(/images/wb-logo-h.svg)) or (mask-image:url(/images/wb-logo-h.svg))){
  .brandlogo{background:var(--ink);
    -webkit-mask:url(/images/wb-logo-h.svg) no-repeat center/contain;
    mask:url(/images/wb-logo-h.svg) no-repeat center/contain}
}
@media(max-width:900px){.brandlogo{height:46px;width:290px}}
@media(max-width:380px){.brandlogo{height:42px;width:265px}}
/* v23 fix: on phones the wordmark is 6.3:1, so at 360-430px it pushed the
   call button clean off the right edge. Below the desktop nav breakpoint the
   brand is allowed to shrink; mask-size:contain scales it down in proportion
   instead of clipping, so the call CTA always stays on screen. */
@media(max-width:899px){
  .nav .brand{flex:0 1 auto;min-width:0}
  .nav .brandlogo{max-width:100%}
}
/* v23 fix: the footer logo was a fixed 403px wide and overflowed its footer
   column by up to 181px, printing over the "Tiles" list. Width-driven now,
   so it shrinks to whatever the column gives it and keeps its ratio. */
.brandlogo-lg{height:auto;width:min(403px,100%);min-width:0;flex:0 1 auto}
@media(max-width:640px){.brandlogo-lg{width:min(340px,100%)}}


/* delivery split hero */
.dl-hero{display:grid;grid-template-columns:1fr 1.15fr;min-height:clamp(340px,48vh,470px);
  padding-top:calc(env(safe-area-inset-top) + var(--navh))}
.dl-left{display:flex;flex-direction:column;justify-content:center;gap:10px;background:var(--bg-elev);
  padding:44px max(var(--gut,20px),calc((100vw - var(--maxw,1120px))/2 + var(--gut,20px))) 44px max(var(--gut,20px),calc((100vw - var(--maxw,1120px))/2 + var(--gut,20px)))}
.dl-title{font-weight:800;font-size:clamp(52px,8.5vw,104px);line-height:.98;letter-spacing:-.03em;
  color:var(--tint);margin:0}
.dl-sub{font-size:clamp(16px,1.8vw,20px);font-weight:600;color:var(--ink);margin:2px 0 0}
.dl-photo{position:relative;overflow:hidden;background:var(--fill2)}
.dl-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.dl-spiel{max-width:760px;margin:0 auto;text-align:center}
.dl-spiel .lead{font-size:clamp(19px,2.2vw,24px);font-weight:700;letter-spacing:-.015em;line-height:1.3}
.dl-spiel p{font-size:16.5px;line-height:1.7;color:var(--label2);margin:14px 0 0}
.dl-spiel b{color:var(--ink)}
@media(max-width:760px){
  .dl-hero{grid-template-columns:1fr}
  .dl-photo{min-height:230px}
  .dl-left{padding-top:30px;padding-bottom:30px}
}


/* Nick round: persistent logo + auto-hiding header (mobile) */
@media(max-width:900px){
  .nav.compact .brand{opacity:1}
  .nav .nav-title{display:none}
  .nav{transition:transform .32s var(--sp2),box-shadow .3s var(--sp2),border-color .3s}
  /* v32 kept the header pinned because Nick read a disappearing logo as
     "his logo from up top is gone". v69 REVERSES that at Luke's request:
     both the header and the tab bar were covering content (his screenshots
     showed the tab bar sitting over the contact form's Email field).
     They now slide away WHILE scrolling and come straight back when the
     scroll stops, so the logo is never gone for more than a moment. */
  .nav.nav-hide{transform:none}
  .nav.chrome-hide{transform:translateY(calc(-100% - 48px))}   /* v84 — clears the inset + shadow */
  body.nav-gone .tsel-bar{top:0}   /* v81 — filter bar docks to the edge while the header is away */
  .tabbar{transition:transform .3s var(--sp2), opacity .24s ease}
  .tabbar.chrome-hide{transform:translateY(calc(100% + 26px));opacity:0;pointer-events:none}
}

.noimg{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;background:linear-gradient(160deg,#f4f2ee,#e9e6e0);color:#6b6f66;text-align:center;padding:12%}.noimg-b{font-size:12px;letter-spacing:.18em;font-weight:700;opacity:.55}.noimg-n{font-size:13px;font-weight:600;line-height:1.35;max-width:100%;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.rangebar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:0 0 14px;padding:12px 14px;border:1px solid var(--sep-op);border-radius:14px;background:var(--bg-elev);color:var(--label)}.rangebar .cap{display:block;font-size:12px;letter-spacing:.12em;text-transform:uppercase;margin-bottom:2px}.rangebar strong{font-size:16px}.ig-tile,.call-tile,.navsearch{position:relative}.ig-tile::after,.call-tile::after,.navsearch::after{content:"";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%);border-radius:12px}
/* ===== v169 — accessibility and motion (css lane) ===== */
/* C16 — "Skip to content" link: off screen until it has keyboard focus, then a pill at the top left */
.skip-link{position:fixed;top:0;left:0;z-index:200;margin:calc(env(safe-area-inset-top) + 10px) 0 0 12px;padding:11px 18px;
  border-radius:999px;background:var(--bg-elev2);color:var(--tint);font-weight:600;font-size:15px;text-decoration:none;
  box-shadow:var(--shadow-lg),inset 0 0 0 1px var(--sep-op);transform:translateY(-200%);transition:none}
.skip-link:focus,.skip-link:focus-visible{transform:none;outline:2.5px solid var(--tint);outline-offset:2px}
/* C16 — strong rings on the big tappable things; the visual tile of the two header buttons */
.btn:focus-visible,.chip:focus-visible,.cchip:focus-visible,.tbtn:focus-visible,.tcard:focus-visible,a.card:focus-visible,button.card:focus-visible,
.sw:focus-visible,.cchart .cc:focus-visible,.lstore:focus-visible,.tab:focus-visible,.icon-btn:focus-visible,.ig-tile:focus-visible,.call-tile:focus-visible,
.hero-dots button:focus-visible,.lqty button:focus-visible,.backbtn:focus-visible{outline:3px solid var(--tint);outline-offset:3px}
.hero .btn:focus-visible,.hero-dots button:focus-visible,.hero-status .badge:focus-visible,.bnr-sw span:focus-visible,.bnr-pill:focus-visible{outline:3px solid #fff;outline-offset:3px}
.searchfield:focus-within{box-shadow:0 0 0 2.5px var(--tint)}
/* B17 — the four header buttons are 44 px wide now (176 px in all): give the wordmark 6 px back on narrow phones */
@media(max-width:480px){.nav-in{gap:8px}}
.ig-tile::before{content:"";position:absolute;inset:7px;z-index:-1;border-radius:9px;background:linear-gradient(45deg,#f9ce34 0%,#ee2a7b 50%,#6228d7 100%)}
.call-tile::before{content:"";position:absolute;inset:7px;z-index:-1;border-radius:9px;background:linear-gradient(180deg,#5CDC6B,#2FBF4C)}
/* C18 / B13 — the pre-rendered copy shows at once (the build no longer writes an inline animation style);
   .noanim is a hook the app can set on the first render after a pre-rendered page */
#prerender .view,#prerender .tcard,.view.noanim,html.noanim .view{animation:none}
#prerender .rise{opacity:1;transform:none;transition:none}
/* C10 / C18 — reduced motion: no entrance animations, no hero crossfade, no transitions */
@media(prefers-reduced-motion:reduce){
  .view,.tcard,.rise,.rise.in,.shim,.note-dot,.bs-track,.btn.lit,.hero-dots button::before{animation:none!important}
  .rise,.rise.in{opacity:1;transform:none;transition:none!important}
  [data-hero],.hero-bg img,.ratio>img,.ratio>a>img,.card,a.card,button.card,.sw,.tcard,.chip,.cchip,.tbtn,.btn,.backbtn,.icon-btn,.ig-tile,.call-tile,
  .nav,.tabbar,.tab-lens,.sheet,.backdrop,.ticker .tk,.ticker .tk.on,.cd-store,.lstore,.tz-card,.row,.nav-title,.nav-links a{transition:none!important}
  a.card:hover,button.card:hover,.sw:hover,.tcard:hover{transform:none}
}

/* v42 — trims tick sheet */
.tz-bar{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:16px;padding:12px 14px;border:1px solid var(--sep);border-radius:14px;background:var(--bg-elev);
  position:sticky;top:calc(var(--navh) + var(--navi,0px) + 8px);z-index:30}
.tz-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(420px,100%),1fr));gap:14px;align-items:start}
.tz-card{padding:14px;cursor:pointer;
  border:1px solid var(--sep);border-radius:16px;background:var(--bg-elev);cursor:pointer;
  transition:border-color .18s var(--sp),background .18s var(--sp)}
.tz-card:hover{border-color:var(--tint)}
.tz-card.on{border-color:var(--tint);background:color-mix(in srgb,var(--tint) 7%,var(--bg-elev))}
.tz-top{display:grid;grid-template-columns:210px 1fr;gap:14px;align-items:start}
.tz-pane{background:var(--fill);border-radius:11px;padding:10px 8px;overflow:hidden}
.tz-pane img{width:100%;height:auto;display:block;border-radius:7px;aspect-ratio:3/2;object-fit:cover;background:var(--bg-elev)}
/* the photo shows the finished product; the cross-section shows the shape a
   tiler actually chooses by. Both, small, one above the other. */
.tz-sec{margin-top:8px;display:flex;align-items:center;gap:7px;padding-top:8px;border-top:1px solid var(--sep-op)}
.tz-sec .tz-svg{width:52px;height:39px;flex:0 0 auto}
.tz-sec span{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--label2)}
/* a grid item defaults to min-width:auto, so this column refused to shrink below
   its longest unbreakable content and pushed the page 5px sideways at 320px.
   Widening the photo column to 210px is what exposed it. */
.tz-body{min-width:0}
/* same story one level down: each spec row is a 2-column grid, and its <dd>
   would not shrink below its longest run of text. */
.tz-specs>div{min-width:0}
.tz-specs dd{min-width:0;overflow-wrap:anywhere}
.tz-tblwrap{margin-top:12px;border:1px solid var(--sep);border-radius:11px;overflow:hidden;cursor:auto}
.tz-tbltitle{padding:7px 11px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--label2);background:var(--fill);border-bottom:1px solid var(--sep)}
.tz-tblwrap{overflow-x:auto}
.tz-tbl{width:100%;border-collapse:collapse;font-size:12px;min-width:340px}
.tz-tbl th{text-align:left;padding:6px 11px;font-size:10.5px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--label2);font-weight:600;white-space:nowrap}
.tz-tbl td{padding:5px 11px;border-top:1px solid var(--sep);white-space:nowrap}
.tz-tbl tbody tr:hover{background:var(--fill)}
.tz-mm{opacity:.55;font-weight:400}
.tz-fin{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin-top:11px;cursor:auto}
.tz-finlab{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--label2);margin-right:3px}
.tz-chip{font-size:11.5px;padding:3px 9px;border:1px solid var(--sep);border-radius:99px;color:var(--label2)}
.tz-chip.tz-sz{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}
.tz-src{text-transform:none;letter-spacing:0;opacity:.65;font-weight:400}
.tz-note{margin:10px 0 0;font-size:12px;line-height:1.5;color:var(--label2)}
.tz-svg{width:100%;height:auto;display:block}
.tz-sub{fill:color-mix(in srgb,var(--ink) 17%,transparent)}
.tz-bed{fill:color-mix(in srgb,var(--ink) 28%,transparent)}
.tz-tile{fill:color-mix(in srgb,var(--ink) 42%,transparent)}
.tz-t{fill:var(--tint)}
.tz-t2{fill:color-mix(in srgb,var(--tint) 68%,transparent)}
.tz-flex{fill:color-mix(in srgb,var(--tint) 38%,transparent)}
.tz-notch{fill:var(--bg-elev)}
.tz-hole{fill:var(--bg-elev)}
.tz-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.tz-name{font-weight:650;letter-spacing:-.01em}
/* v46 — 23px tall, one pixel under the WCAG 2.2 AA minimum tap target of 24.
   The whole card is tappable as well, but there is no reason for the label
   itself to be short. */
.tz-tick{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--label2);white-space:nowrap;min-height:28px}
.tz-tick input{width:17px;height:17px;accent-color:var(--tint)}
.tz-use{margin:6px 0 10px;font-size:13.5px;line-height:1.5;color:var(--label2)}
/* min-height 28px: the first cut was 18px tall and failed the 24px WCAG 2.2
   tap-target minimum — caught by the same harness that caught the tick label. */
.tz-plink{display:inline-flex;align-items:center;min-height:28px;margin:-4px 0 6px;font-size:12.5px;font-weight:600}
.tz-specs{margin:0;display:grid;gap:4px}
.tz-specs div{display:grid;grid-template-columns:70px 1fr;gap:10px;font-size:12.5px}
.tz-specs dt{margin:0;color:var(--label2);text-transform:uppercase;letter-spacing:.05em;font-size:10.5px;padding-top:2px}
.tz-specs dd{margin:0}
.tz-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.45;word-break:break-word;color:var(--label2)}
@media(max-width:640px){.tz-top{grid-template-columns:132px 1fr;gap:11px}.tz-card{padding:11px}
  .tz-specs div{grid-template-columns:66px 1fr}}


/* v169 glue */
#main:focus-visible{outline:0}
