/* Self-hosted so the critical path carries no third-party origin: the Google Fonts
   stylesheet was render-blocking and pulled in two more connections
   (fonts.googleapis.com, then fonts.gstatic.com) before any text could paint.
   Manrope and Playfair Display are both SIL Open Font License 1.1.
   Latin + Latin-Ext only; the site has no other scripts. */

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/manrope-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/manrope-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/assets/fonts/manrope-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/assets/fonts/manrope-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/manrope-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/manrope-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/assets/fonts/manrope-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/assets/fonts/manrope-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url(/assets/fonts/manrope-800-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url(/assets/fonts/manrope-800-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/playfair-display-400-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/playfair-display-400-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/playfair-display-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/playfair-display-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}

:root{
  /* a cool near-white, to sit with the black mark rather than warm it */
  --bg:#F4F4F5;
  --card:#FFFFFF;
  --tint:#ECECEE;
  --hair:#DCDCDE;
  --hair-soft:#E8E8EA;

  --ink:#0B0B0D;      /* headings, product names, and the accent - the logo is black */
  --ink2:#55555C;     /* body + all secondary text: 7.2:1 on white */
  --ink3:#66666D;     /* the lightest text used anywhere: clears 4.5:1 on both grounds */

  /* ELKY green, sampled off the signage photo (#576E4E) with the saturation the camera
     washed out put back, and darkened until white type on it clears AA comfortably.
     Change these two and every button, chip, badge and focus ring follows. */
  --acc:#47683B;      /* white on this is 6.3:1 */
  --acc-d:#37522E;    /* hover: unlike black, green can go darker */
  --shopee:#EE4D2D;   /* used only as a recognition cue, never as a large field */


/* ═══ Type and spacing scale ═════════════════════════════════════════════════
   Before this there were 32 distinct type sizes and 48 spacing values, including
   eleven sizes between 12px and 17px that nobody can tell apart, six different
   sizes of h2 depending on the section, and an h4 rule larger than three separate
   h3 rules. Every new component was re-deciding what a section heading looks like.

   Eight type steps and eight spacing steps. Rounded to the nearest step, so a few
   things move by a pixel or two; that is the point. --t-xs is the floor at 12px,
   which also retires the 11px and 11.5px that had crept in against the rule below. */
  --t-xs:12px;                      /* kickers, captions, legal */
  --t-sm:13px;                      /* meta, card prices */
  --t-md:15px;                      /* UI text, secondary copy */
  --t-body:17px;                    /* body copy */
  --t-xl:20px;                      /* h3, leads */
  --t-h2:clamp(22px,2.4vw,26px);    /* every h2 */
  --t-h1:clamp(26px,3.4vw,40px);    /* page h1 */
  --t-hero:clamp(30px,4.2vw,52px);  /* hero only */


  /* Responsive spacing. Eighteen one-off clamps said the same few things in
     slightly different ways; these are the four sizes that were actually meant. */
  --sr-1:clamp(10px,2vw,18px);
  --sr-2:clamp(16px,2.4vw,26px);
  --sr-3:clamp(24px,3.4vw,40px);
  --sr-4:clamp(34px,4.6vw,56px);
  --sr-5:clamp(48px,6.4vw,88px);

  --s-1:4px;   --s-2:8px;   --s-3:12px;  --s-4:16px;
  --s-5:24px;  --s-6:32px;  --s-7:48px;  --s-8:clamp(48px,6vw,72px);

  --nav-h:52px;
  --r:18px;
  --r-sm:12px;
}

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:'Manrope',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  background:var(--bg);
  color:var(--ink);
  font-size:var(--t-body);
  line-height:1.5;
  letter-spacing:-.01em;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
input,select{font:inherit;color:inherit}

.wrap{width:min(1180px,100% - 44px);margin-inline:auto}
@media(max-width:600px){.wrap{width:min(1180px,100% - 32px)}}
.narrow{max-width:760px;margin-inline:auto}
.center{text-align:center}
.num{font-variant-numeric:tabular-nums}

h1,h2,h3,h4{letter-spacing:-.03em;line-height:1.08;text-wrap:balance;font-weight:800}
.t-hero{font-size:var(--t-hero)}
.t-sec{font-size:var(--t-h1)}
.lead{font-size:var(--t-xl);line-height:1.45;color:var(--ink2);font-weight:500;letter-spacing:-.015em}
/* wide-tracked uppercase, echoing the spacing in the ELKY wordmark */
.eyebrow{font-size:var(--t-xs);font-weight:700;letter-spacing:.22em;text-transform:uppercase;color:var(--ink3)}

/* ─────────── NAV ─────────── */
.nav{position:sticky;top:0;z-index:70;height:var(--nav-h);
  background:rgba(249,249,250,.82);backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid var(--hair-soft)}
.nav-in{display:flex;align-items:center;gap:var(--s-2);height:var(--nav-h)}
.mark{display:block;height:27px;width:auto;flex-shrink:0}
@media(max-width:400px){.mark{height:23px}}
.nav-links{display:flex;gap:var(--s-1);margin:0 auto}
.nav-links a{font-size:var(--t-sm);font-weight:600;color:var(--ink2);padding:var(--s-2) var(--s-3);border-radius:8px;transition:color .15s,background .15s}
.nav-links a:hover{color:var(--ink);background:rgba(0,0,0,.045)}
@media(max-width:900px){.nav-links{display:none}}
.nav-shop{margin-left:auto;font-size:var(--t-sm);font-weight:700;color:#fff;background:var(--acc);
  display:inline-flex;align-items:center;gap:var(--s-1);padding:var(--s-2) var(--s-4);border-radius:99px;transition:background .15s;white-space:nowrap}
.nav-shop:hover{background:var(--acc-d)}
.nav-shop svg{width:15px;height:15px;stroke:currentColor;stroke-width:1.9;fill:none}

/* ─────────── HERO ───────────
   Full-bleed photograph with the copy over it. Held to ~56vh rather than a full screen:
   the category strip stays visible underneath, so the page still opens onto the goods.
   The scrim is heavy because it has to be - the photo is a bright white kitchen, and
   white type over it is nowhere near 4.5:1 unadorned. */
.hero{position:relative;isolation:isolate;display:grid;place-items:center;text-align:center;
  min-height:clamp(360px,56vh,520px);padding:var(--sr-5) 0;background:#0B0B0D;overflow:hidden}
.hero-bg{position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover;object-position:center}
.hero::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(8,8,10,.56) 0%,rgba(8,8,10,.64) 48%,rgba(8,8,10,.76) 100%)}
.hero-copy{position:relative;max-width:940px;margin-inline:auto;color:#fff}
/* hairlines either side of the eyebrow */
/* .92 rather than .84: at 12px this is small text, so it needs 4.5:1 against the
   brightest pixel of the photo behind it, and .84 measured 4.51 - no headroom */
.hero .eyebrow{color:rgba(255,255,255,.92);display:flex;align-items:center;justify-content:center;
  gap:var(--sr-1);margin-bottom:var(--sr-2)}
.hero .eyebrow::before,.hero .eyebrow::after{content:"";height:1px;flex:0 0 clamp(22px,5vw,56px);
  background:rgba(255,255,255,.5)}
/* on a phone the full eyebrow plus its two rules will not fit on one line, and wrapping
   leaves the rules stranded on the first line with a word orphaned under them. Tighten
   the tracking and drop the rules instead. */
/* Too long for one line on a phone, so it has to break somewhere. Two things to get
   right: the eyebrow is a flex row (for the hairlines), and any inner element becomes a
   second flex item that sits beside the text instead of wrapping with it - so drop back
   to a normal text block here, where the hairlines are hidden anyway. Then keep the
   descriptor whole so the break lands at the separator, not mid-hyphen through
   "space-saving". */
@media(max-width:600px){
  .hero .eyebrow{display:block;font-size:var(--t-xs);letter-spacing:.14em}
  .hero .eyebrow::before,.hero .eyebrow::after{display:none}
  /* the descriptor is ~200px, so it fits any phone column without an escape hatch */
  .hero .eyebrow .nb{white-space:nowrap}
}
/* one line now, so it can take more size. Italic because that is the line the roman
   "The ELKY range." was setting up, and it reads as the statement rather than a label. */
.hero h1{font-family:'Playfair Display',Georgia,'Times New Roman',serif;font-weight:400;
  font-style:italic;font-size:var(--t-hero);line-height:1.06;letter-spacing:-.005em;color:#fff}
.hero-cta{display:flex;gap:var(--s-3);justify-content:center;flex-wrap:wrap;margin-top:var(--sr-3)}
.btn-hero{display:inline-flex;align-items:center;gap:var(--s-2);font-size:var(--t-xs);font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;padding:var(--s-4) var(--s-5);border:1px solid transparent;
  border-radius:2px;transition:background .16s,border-color .16s,color .16s}
.btn-hero svg{width:15px;height:15px;stroke:currentColor;stroke-width:2;fill:none;flex-shrink:0}
.btn-hero.solid{background:#fff;color:var(--ink)}
.btn-hero.solid:hover{background:rgba(255,255,255,.85)}
.btn-hero.ghost{border-color:rgba(255,255,255,.55);color:#fff}
.btn-hero.ghost:hover{border-color:#fff;background:rgba(255,255,255,.12)}
@media(max-width:480px){.btn-hero{flex:1 1 100%;justify-content:center}}

/* ─────────── CATEGORY TILES ─────────── */
.sec{padding:var(--sr-4) 0 var(--sr-2)}
.sec-hd{margin-bottom:var(--s-4);display:flex;align-items:baseline;gap:var(--s-3);flex-wrap:wrap}
.sec-hd h2{font-size:var(--t-h2)}

/* six across and image-led, but short: this is a shortcut into the grid below, not a
   feature panel, so it does not get a screen of its own */
.tiles{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--s-3)}
@media(max-width:1000px){.tiles{grid-template-columns:repeat(3,1fr)}}
/* on a phone the six become one swipeable row rather than three stacked rows - that is
   ~400px less between the hero and the first product */
@media(max-width:700px){
  .tiles{display:flex;gap:var(--s-2);overflow-x:auto;scroll-snap-type:x proximity;
    margin-inline:-16px;padding:var(--s-1) var(--s-4);scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .tiles::-webkit-scrollbar{display:none}
  .tile{flex:0 0 130px;scroll-snap-align:start}
}
.tile{background:var(--card);border-radius:var(--r-sm);padding:var(--s-3) var(--s-2) var(--s-3);text-align:center;
  display:flex;flex-direction:column;align-items:center;transition:transform .2s ease,box-shadow .2s ease}
.tile:hover{transform:translateY(-3px);box-shadow:0 10px 26px rgba(11,11,13,.11)}
.tile-img{position:relative;width:100%;aspect-ratio:4/3;margin-bottom:var(--s-2)}
.tile-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:8%}
.tile h3{font-size:var(--t-md);font-weight:700;letter-spacing:-.02em;line-height:1.2}
.tile span{font-size:var(--t-xs);font-weight:600;color:var(--ink3);margin-top:var(--s-1)}
.tile[aria-selected="true"]{outline:1.5px solid var(--acc);outline-offset:-1.5px}

/* ─────────── FILTER BAR ─────────── */
/* the anchor sits above the sticky strip, so jumping to it has to clear both the nav
   and the strip or the toolbar lands underneath them */
#catalogue,#about{scroll-margin-top:var(--nav-h)}
.bar{position:sticky;top:var(--nav-h);z-index:60;background:rgba(249,249,250,.9);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid var(--hair-soft);padding:var(--s-2) 0}
/* one line, always - it scrolls sideways on narrow screens rather than growing taller */
.chips{display:flex;gap:var(--s-1);justify-content:center;flex-wrap:nowrap;overflow-x:auto;
  scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch}
.chips::-webkit-scrollbar{display:none}
@media(max-width:820px){.chips{justify-content:flex-start;margin-inline:-16px;padding-inline:var(--s-4)}}
.chip{font-size:var(--t-md);font-weight:600;color:var(--ink2);padding:var(--s-2) var(--s-4);border-radius:99px;
  background:transparent;transition:background .15s,color .15s;letter-spacing:-.01em;white-space:nowrap}
.chip:hover{background:rgba(0,0,0,.055);color:var(--ink)}
.chip[aria-selected="true"]{background:var(--acc);color:#fff}

.toolbar{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;margin-top:var(--s-5)}
/* 360px, not the 250px this used to be. The longest placeholder - "Search kitchen
   baskets & pull-out storage" - measures 294px at 15px Manrope, and the field carries
   32px of left padding for the icon plus 12px on the right, so 338px is the floor.
   360 leaves a little slack for font fallbacks. It may grow into a wide row but stops
   at 520px, past which a search field starts to look like a mistake. */
.find{position:relative;flex:1 1 360px;min-width:min(340px,100%);max-width:520px}
.find svg{position:absolute;left:13px;top:50%;transform:translateY(-50%);width:16px;height:16px;stroke:var(--ink3);stroke-width:2;fill:none;pointer-events:none}
.find input{width:100%;padding:var(--s-2) var(--s-3) var(--s-2) var(--s-6);border:1px solid var(--hair);border-radius:99px;
  background:var(--card);font-size:var(--t-md);font-weight:500;outline:none;transition:border-color .15s,box-shadow .15s}
.find input::placeholder{color:var(--ink3)}
.find input:focus{border-color:var(--ink3);box-shadow:0 0 0 4px rgba(11,11,13,.07)}
.pick{padding:var(--s-2) var(--s-6) var(--s-2) var(--s-4);border:1px solid var(--hair);border-radius:99px;background:var(--card);
  font-size:var(--t-md);font-weight:600;cursor:pointer;outline:none;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' stroke='%23767679' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 13px center;background-size:12px}
.pick.hide{display:none}
/* the sub-filter reads as "on" when it is doing something */
.pick.active{background-color:var(--acc);border-color:var(--acc);color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' stroke='%23ffffff' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}

/* ─────────── PRODUCT GRID ─────────── */
.result{font-size:var(--t-md);font-weight:600;color:var(--ink2);margin-left:auto}
/* on a phone: search on its own line, the two menus sharing the next one */
@media(max-width:700px){
  .result{margin-left:0;width:100%}
  .find{flex:1 1 100%}
  .pick{flex:1 1 calc(50% - 5px);min-width:0}
}
/* denser than the old 238px track: six across at 1180px instead of four, so a page of
   36 products is six rows rather than nine */
/* the grid is the last thing before the footer now, so the section carries the gap -
   put on the section rather than the pager, which is hidden on a single-page result */
.catalogue{padding-bottom:var(--sr-4)}
.grid{margin-top:var(--s-4);display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:var(--s-3);align-items:stretch}
@media(max-width:600px){.grid{grid-template-columns:repeat(2,1fr);gap:var(--s-2)}}

.item{position:relative;display:flex;flex-direction:column;background:var(--card);border-radius:var(--r);
  padding:var(--s-4) var(--s-4);text-align:center;transition:transform .22s ease,box-shadow .22s ease}
.item:hover{transform:translateY(-5px);box-shadow:0 12px 34px rgba(11,11,13,.12)}
/* A fixed 4:5 portrait window, the same on every card whatever shape the photo is.
   The image is taken out of flow and told to fill the window with object-fit:contain,
   so it scales down until it fits and never crops. Absolute rather than a flex child
   with max-height:88%: a percentage height against a box sized by aspect-ratio does not
   reliably resolve, and a tall photo would then render at its natural height and stretch
   its own card - which is exactly what these were doing. */
.item-img{position:relative;aspect-ratio:4/5;margin-bottom:var(--s-3);flex:0 0 auto}
.item-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:6%}
.flag{position:absolute;top:0;left:0;font-size:var(--t-xs);font-weight:700;color:var(--ink2);
  background:var(--tint);padding:var(--s-1) var(--s-2);border-radius:99px;letter-spacing:-.005em}
.flag.sizes{left:auto;right:0}
.flag.deal{background:var(--acc);color:#fff}

.kicker{font-size:var(--t-xs);font-weight:700;color:var(--ink3);letter-spacing:.01em;margin-bottom:var(--s-1)}
.name{font-size:var(--t-body);font-weight:700;letter-spacing:-.02em;line-height:1.25;overflow-wrap:anywhere}
.foot{margin-top:auto;padding-top:var(--s-4)}
.cost{font-size:var(--t-body);font-weight:600;color:var(--ink2);letter-spacing:-.015em}
.cost b{font-weight:700;color:var(--ink)}
/* both checkout routes sit on the card. flex-basis 84px with wrap means they sit side by
   side on a desktop card and stack on a phone one, without a second media query */
.buys{display:flex;flex-wrap:wrap;gap:var(--s-1);margin-top:var(--s-3);position:relative;z-index:2}
.buy{flex:1 1 84px;display:inline-flex;align-items:center;justify-content:center;gap:var(--s-1);
  background:var(--acc);color:#fff;font-size:var(--t-sm);font-weight:700;padding:var(--s-2) var(--s-3);border-radius:99px;
  transition:background .15s,border-color .15s;letter-spacing:-.01em;white-space:nowrap}
.item:hover .buy{background:var(--acc-d)}
.buy svg{width:14px;height:14px;fill:currentColor;flex-shrink:0}
.buy.alt{background:transparent;color:var(--ink);border:1px solid var(--hair)}
.item:hover .buy.alt{background:transparent;border-color:var(--acc)}
/* the installation call-out: green so it reads as an offer rather than fine print */
.install{font-size:var(--t-xs);font-weight:700;color:var(--acc);margin-top:var(--s-1);letter-spacing:-.005em}
.install::before{content:"+ "}
.install-lg{font-size:var(--t-md);font-weight:600;line-height:1.45;margin:var(--s-4) 0 0}
.install-lg::before{content:""}
.pv-none{font-size:var(--t-md);font-weight:600;color:var(--ink3);margin-top:var(--s-4)}
.cover{position:absolute;inset:0;z-index:1;border-radius:var(--r)}

/* Numbered pages rather than "load more": the page stops growing, and you can jump to
   the end instead of scrolling to it. */
.pager{display:flex;justify-content:center;align-items:center;gap:var(--s-1);margin:var(--s-6) 0 var(--s-1);flex-wrap:wrap}
.pager button{min-width:38px;height:38px;padding:0 var(--s-3);border-radius:99px;font-size:var(--t-md);font-weight:700;
  color:var(--ink2);font-variant-numeric:tabular-nums;transition:background .15s,color .15s}
.pager button:hover:not(:disabled){background:var(--tint);color:var(--ink)}
.pager button[aria-current="true"]{background:var(--acc);color:#fff}
.pager button:disabled{color:var(--hair);cursor:default}
.pager .gap{color:var(--ink3);padding:0 var(--s-1);font-weight:600}
.pager[hidden]{display:none}

/* appears once you are past the first screen; keeps the trip back short */
.totop{position:fixed;right:20px;bottom:20px;z-index:65;width:42px;height:42px;border-radius:99px;
  background:var(--acc);color:#fff;display:flex;align-items:center;justify-content:center;
  box-shadow:0 6px 20px rgba(11,11,13,.28);opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .2s,transform .2s,visibility .2s}
.totop.on{opacity:1;visibility:visible;transform:none}
.totop svg{width:18px;height:18px;stroke:currentColor;stroke-width:2.2;fill:none}
@media(max-width:600px){.totop{right:14px;bottom:14px}}

.none{grid-column:1/-1;text-align:center;padding:var(--s-8) var(--s-4)}
.none b{display:block;font-size:var(--t-xl);font-weight:800;letter-spacing:-.025em;margin-bottom:var(--s-2)}
.none span{color:var(--ink2);font-weight:500}

/* ─────────── ABOUT (about page only) ─────────── */
.about{background:var(--card);padding:var(--sr-5) 0}
.about-top{text-align:center;margin-bottom:var(--sr-4)}
/* the ELKY mark is a wide wordmark (4.1:1), so it is set by height and stays modest */
.about-mark{height:clamp(44px,5.5vw,66px);width:auto;margin:0 auto var(--s-5)}
.about-top .lead{max-width:56ch;margin-inline:auto}
.about-cols{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-6);
  border-top:1px solid var(--hair-soft);padding-top:var(--sr-4)}
@media(max-width:820px){.about-cols{grid-template-columns:1fr;gap:var(--s-5)}}
.about-cols h4{font-size:var(--t-body);font-weight:700;margin-bottom:var(--s-2)}
.about-cols p{font-size:var(--t-body);color:var(--ink2);font-weight:500;line-height:1.55}
/* ─────────── DISTRIBUTORS ───────────
   One card per place the range can be bought. Adding another Shopee store is a copy of
   one <a class="dist"> block in the about section of _data/page.html. */
.dists{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--s-3);
  margin-top:var(--sr-4)}
.dist{display:flex;flex-direction:column;background:var(--bg);border:1px solid var(--hair-soft);
  border-radius:var(--r);padding:var(--s-5) var(--s-5) var(--s-4);transition:border-color .18s,transform .18s,box-shadow .18s}
.dist:hover{border-color:var(--acc);transform:translateY(-3px);box-shadow:0 10px 26px rgba(11,11,13,.1)}
.dist-k{font-size:var(--t-xs);font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink3);margin-bottom:var(--s-2)}
.dist h4{font-size:var(--t-body);font-weight:800;margin-bottom:var(--s-1)}
.dist-url{font-size:var(--t-sm);font-weight:600;color:var(--ink3);margin-bottom:var(--s-2);overflow-wrap:anywhere}
.dist p{font-size:var(--t-md);color:var(--ink2);font-weight:500;line-height:1.5}
.dist-go{margin-top:var(--s-3);font-size:var(--t-md);font-weight:700;color:var(--ink);display:inline-flex;align-items:center;gap:var(--s-1)}
.dist-go::after{content:"›";font-size:var(--t-body);line-height:1;transition:transform .18s}
.dist:hover .dist-go::after{transform:translateX(3px)}


/* ─────────── FOOTER ─────────── */
.foot-w{border-top:1px solid var(--hair-soft);padding:var(--s-7) 0 var(--s-6);font-size:var(--t-md);color:var(--ink2)}
.foot-mark{height:30px;margin-bottom:var(--s-6)}
.foot-g{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-5)}
@media(max-width:760px){.foot-g{grid-template-columns:repeat(2,1fr);gap:var(--s-5)}}
/* The catalogue's footer uses h5, the generated site uses h2. This rule only named
   h5, so on the site the footer headings matched nothing and fell back to the
   browser's 1.5em default: 22.5px, larger than several real section headings. */
.foot-w h5,.foot-w h2{font-size:var(--t-sm);font-weight:800;color:var(--ink);margin-bottom:var(--s-3);letter-spacing:-.01em}
.foot-w ul{list-style:none;display:flex;flex-direction:column;gap:var(--s-2)}
.foot-w li{font-weight:500;line-height:1.4}
.foot-w a{transition:color .15s}
.foot-w a:hover{color:var(--ink)}
.fine{margin-top:var(--s-6);padding-top:var(--s-4);border-top:1px solid var(--hair-soft);
  display:flex;justify-content:space-between;gap:var(--s-3);flex-wrap:wrap;font-size:var(--t-sm);color:var(--ink2);font-weight:500}

/* ─────────── PRODUCT PANEL ─────────── */
dialog{border:none;padding:0;background:var(--card);color:var(--ink);max-width:none;max-height:none}
dialog::backdrop{background:rgba(11,11,13,.45);backdrop-filter:blur(3px)}
.sheet{width:min(880px,calc(100vw - 32px));max-height:min(88vh,900px);border-radius:22px;
  margin:auto;overflow:auto;overscroll-behavior:contain}

.dlg-x{position:absolute;top:14px;right:14px;z-index:3;width:32px;height:32px;border-radius:99px;
  background:var(--tint);color:var(--ink2);font-size:var(--t-xl);line-height:1;display:flex;
  align-items:center;justify-content:center;transition:.15s}
.dlg-x:hover{background:var(--hair);color:var(--ink)}

.pv{position:relative;padding:var(--s-6)}
@media(max-width:640px){.pv{padding:var(--s-5) var(--s-4)}}
.pv-top{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-6);align-items:start}
@media(max-width:700px){.pv-top{grid-template-columns:1fr;gap:var(--s-5)}}
.pv-img{position:relative;background:var(--bg);border-radius:16px;aspect-ratio:1}
.pv-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:var(--s-5)}
.pv-thumbs{display:flex;gap:var(--s-2);margin-top:var(--s-2);flex-wrap:wrap}
.pv-thumb{width:56px;height:56px;border-radius:10px;background:var(--bg);padding:var(--s-1);
  border:1.5px solid transparent;transition:border-color .15s}
.pv-thumb img{width:100%;height:100%;object-fit:contain}
.pv-thumb[aria-current="true"]{border-color:var(--acc)}
.pv-kick{font-size:var(--t-xs);font-weight:700;color:var(--ink3);margin-bottom:var(--s-2)}
.pv h3{font-size:var(--t-xl);font-weight:800;letter-spacing:-.03em;line-height:1.14;margin-bottom:var(--s-1);overflow-wrap:anywhere}
.pv-code{font-size:var(--t-sm);font-weight:600;color:var(--ink3);overflow-wrap:anywhere}
.pv-price{font-size:var(--t-h2);font-weight:800;letter-spacing:-.03em;margin:var(--s-4) 0 var(--s-1);font-variant-numeric:tabular-nums}
.pv-price small{font-size:var(--t-md);font-weight:600;color:var(--ink2);letter-spacing:-.01em}

/* two checkout routes, equal weight - one filled, one outlined, same size */
.pv-acts{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-4)}
.pv-acts a{flex:1 1 150px;display:flex;align-items:center;justify-content:center;gap:var(--s-2);
  font-size:var(--t-md);font-weight:700;padding:var(--s-3) var(--s-4);border-radius:99px;text-align:center;
  border:1px solid transparent;transition:background .15s,border-color .15s}
.btn-shopee{background:var(--acc);color:#fff}
.btn-shopee:hover{background:var(--acc-d)}
.pv-acts svg{width:17px;height:17px;fill:currentColor;flex-shrink:0}
.pv-lbl{font-size:var(--t-xs);font-weight:700;color:var(--ink3);margin:var(--s-4) 0 -6px;width:100%}
.pv-note{font-size:var(--t-sm);color:var(--ink3);font-weight:500;margin-top:var(--s-3);line-height:1.45}

.pv-spec{margin-top:var(--s-6);padding-top:var(--s-5);border-top:1px solid var(--hair-soft)}
.pv-spec h4:first-child{margin-top:0}
.pv-spec-t{font-size:var(--t-xs);font-weight:700;color:var(--ink3);margin-bottom:var(--s-3)}
.pv-body{font-size:var(--t-md);color:var(--ink2);line-height:1.6;font-weight:500}
.pv-body h4{font-size:var(--t-body);font-weight:700;color:var(--ink);margin:var(--s-5) 0 var(--s-2);letter-spacing:-.02em}
.pv-body p{margin:0 0 var(--s-2)}
.pv-body ul,.pv-body ol{margin:0 0 var(--s-3);padding-left:var(--s-4)}
.pv-body li{margin-bottom:var(--s-1)}
.pv-body strong{color:var(--ink);font-weight:700}
.pv-body a{color:var(--ink);font-weight:700;text-decoration:underline;text-underline-offset:2px}
.pv-body img{max-width:100%;height:auto;border-radius:10px;margin:var(--s-2) 0}
.pv-body table{border-collapse:collapse;width:100%;font-size:var(--t-md);margin:var(--s-2) 0}
.pv-body th,.pv-body td{border:1px solid var(--hair);padding:var(--s-2) var(--s-3);text-align:left}
.pv-body th{background:var(--bg);font-weight:700;color:var(--ink)}
.pv-scroll{overflow-x:auto}

/* ─────────── A11Y ─────────── */
:focus-visible{outline:2px solid var(--acc);outline-offset:3px;border-radius:8px}
.item:focus-within,.tile:focus-within{box-shadow:0 12px 34px rgba(11,11,13,.12)}
.skip{position:absolute;left:-9999px}
.skip:focus{left:12px;top:8px;z-index:100;background:var(--card);padding:var(--s-2) var(--s-4);border-radius:8px;font-weight:700}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .item:hover,.tile:hover,.dist:hover{transform:none}
  .dist:hover .dist-go::after{transform:none}
}

/* Styles for the multi-page site only. Appended to the catalogue's stylesheet by
   site.js, so the shared look (palette, nav, grid, cards, hero) comes from page.html and
   only what the extra page types need lives here. */

.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ── breadcrumbs ─────────────────────────────────────────────────────────── */
.crumbs{padding:var(--s-3) 0 0}
.crumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:var(--s-1);font-size:var(--t-sm);font-weight:600;color:var(--ink3)}
/* The chevron was --hair at 1.25:1 against the page, which is invisible rather than
   subtle. --ink3 is 5.18:1 and already on the scale; weight 400 against the items'
   600 keeps it reading as a separator rather than another word. */
.crumbs li+li::before{content:"›";margin-right:var(--s-1);color:var(--ink3);font-weight:400}
/* The trail read as one flat string because the current page was styled exactly
   like the link before it. It already carries aria-current, so no markup changes. */
.crumbs [aria-current="page"]{color:var(--ink);font-weight:700}
.crumbs a{color:var(--ink3)}
.crumbs a:hover{color:var(--acc)}

/* ── category page ───────────────────────────────────────────────────────── */
.cat{padding-bottom:var(--s-8)}
.cat-hd{padding:var(--s-3) 0 var(--s-4);max-width:66ch}
.cat-hd h1{font-size:var(--t-h1);margin-bottom:var(--s-3)}
.cat-hd .lead{margin-bottom:var(--s-2)}
.cat-count{font-size:var(--t-md);font-weight:700;color:var(--ink3)}

.faq{margin-top:var(--s-8);border-top:1px solid var(--hair-soft);padding-top:var(--s-6);max-width:760px}
.faq h2{font-size:var(--t-h2);margin-bottom:var(--s-3)}
.faq details{border-bottom:1px solid var(--hair-soft);padding:var(--s-3) 0}
.faq summary{font-size:var(--t-body);font-weight:700;cursor:pointer;list-style:none;display:flex;justify-content:space-between;gap:var(--s-3)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";color:var(--acc);font-weight:700;flex-shrink:0}
.faq details[open] summary::after{content:"–"}
.faq p{font-size:var(--t-md);color:var(--ink2);font-weight:500;line-height:1.55;margin-top:var(--s-2)}

.cat-nav{margin-top:var(--sr-4);border-top:1px solid var(--hair-soft);padding-top:var(--sr-3)}
.cat-nav h2{font-size:var(--t-h2);margin-bottom:var(--s-3)}
.cat-nav ul{list-style:none;display:flex;flex-wrap:wrap;gap:var(--s-2)}
.cat-nav a{display:inline-block;font-size:var(--t-md);font-weight:600;padding:var(--s-2) var(--s-4);border:1px solid var(--hair);border-radius:99px;transition:border-color .15s,background .15s}
.cat-nav a:hover{border-color:var(--acc);background:var(--tint)}

/* ── product page ────────────────────────────────────────────────────────── */
.pd{padding-bottom:var(--s-8)}
.pd-top{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:var(--sr-3);
  align-items:start;padding:var(--sr-1) 0 var(--sr-3)}
@media(max-width:820px){.pd-top{grid-template-columns:1fr;gap:var(--s-5)}}
.pd-hero{width:100%;height:auto;aspect-ratio:4/5;object-fit:contain;background:var(--card);
  border-radius:var(--r);padding:5%}
.pd-thumbs{display:flex;gap:var(--s-2);margin-top:var(--s-2);flex-wrap:wrap}
.pd-thumbs img{width:76px;height:76px;object-fit:contain;background:var(--card);border-radius:10px;padding:var(--s-1)}
.pd-info h1{font-size:var(--t-h1);margin:var(--s-1) 0 var(--s-2)}
.pd-code{font-size:var(--t-sm);font-weight:600;color:var(--ink3);overflow-wrap:anywhere}
.pd-price{font-size:var(--t-h2);font-weight:800;letter-spacing:-.03em;margin:var(--s-4) 0 var(--s-1)}
.pd-meta{font-size:var(--t-md);font-weight:600;color:var(--ink2)}
.pd-buy{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-5)}
/* layout only here. Setting `border` on `.pd-buy a` would beat the skin below on
   specificity and flatten the button into plain text, so the skin is restated at
   this depth instead. */
.pd-buy a{flex:1 1 200px;display:flex;align-items:center;justify-content:center;
  font-size:var(--t-md);font-weight:700;padding:var(--s-4) var(--s-5);border-radius:99px;text-align:center;
  transition:background .15s,border-color .15s}
.pd-buy .btn-shopee{background:var(--acc);color:#fff;border:1px solid var(--acc)}
.pd-buy .btn-shopee:hover{background:var(--acc-d);border-color:var(--acc-d)}
.pd-note{font-size:var(--t-sm);color:var(--ink3);font-weight:500;margin-top:var(--s-3);line-height:1.5}

.pd-spec,.pd-about,.pd-more{border-top:1px solid var(--hair-soft);padding-top:var(--s-6);
  margin-top:var(--s-6)}
.pd-spec h2,.pd-about h2,.pd-more h2{font-size:var(--t-h2);margin-bottom:var(--s-3)}
.pd-about p{font-size:var(--t-body);color:var(--ink2);font-weight:500;line-height:1.6;max-width:70ch;margin-bottom:var(--s-2)}
.pd-about a{color:var(--acc);font-weight:700;text-decoration:underline;text-underline-offset:2px}
.more-link{margin-top:var(--s-4)}
.more-link a{font-size:var(--t-md);font-weight:700;color:var(--acc)}

/* ── home ────────────────────────────────────────────────────────────────── */
.home .sec{padding:var(--sr-4) 0;border-bottom:1px solid var(--hair-soft)}
.home .sec:last-child{border-bottom:none}
.home .sec h2{font-size:var(--t-h2);margin-bottom:var(--s-3)}
.home .sec .lead{max-width:68ch;margin-bottom:var(--s-5)}

/* four across, to match the product grid, rather than as many as happen to fit */
/* One row, scrolled, rather than a grid that wrapped to two rows on a desktop and
   three on a phone. Six collections is a short list and it should read as one: a
   visitor should see the whole range without scrolling the page. The cards are
   small enough that all six fit inside 1180px on a desktop, so the scroll only
   engages on narrower screens. Same scroll-snap pattern as the product rails, no
   script, and every card is still a real link in the HTML. */
.cat-cards{display:flex;gap:var(--s-3);overflow-x:auto;scroll-snap-type:x proximity;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;padding:2px 2px var(--s-2)}
.cat-cards::-webkit-scrollbar{display:none}
.cat-card{flex:0 0 150px;scroll-snap-align:start}
@media(max-width:600px){
  /* full-bleed so a card is never sliced by the page gutter */
  .cat-cards{margin-inline:calc(var(--s-4) * -1);padding-inline:var(--s-4);
    scroll-padding-left:var(--s-4)}
  .cat-card{flex-basis:124px}
}
.cat-card{background:var(--card);border-radius:var(--r);padding:var(--s-3);text-align:center;
  display:flex;flex-direction:column;align-items:center;transition:transform .2s,box-shadow .2s}
.cat-card:hover{transform:translateY(-3px);box-shadow:0 10px 26px rgba(11,11,13,.11)}
.cat-card-img{width:100%;aspect-ratio:1;position:relative;margin-bottom:var(--s-2)}
.cat-card-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:6%}
.cat-card h3{font-size:var(--t-sm);font-weight:700;line-height:1.28}

.why-g{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--s-4)}
.why-g h3{font-size:var(--t-xl);font-weight:700;margin-bottom:var(--s-2)}
.why-g p{font-size:var(--t-md);color:var(--ink2);font-weight:500;line-height:1.55}

/* ── about ───────────────────────────────────────────────────────────────── */
.about-p{max-width:760px;padding-bottom:var(--s-8)}
.about-p h1{font-size:var(--t-h1);margin:var(--s-4) 0 var(--s-3)}
.about-p h2{font-size:var(--t-h2);margin:var(--s-6) 0 var(--s-2)}
.about-p p{font-size:var(--t-body);color:var(--ink2);font-weight:500;line-height:1.65}
.about-p .lead{margin-bottom:var(--s-2)}
.about-p a{color:var(--acc);font-weight:700;text-decoration:underline;text-underline-offset:2px}
.about-p .about-mark{height:clamp(40px,5vw,58px);width:auto;margin-top:var(--s-5)}

/* the grid cards link out rather than opening a panel, so the whole card is a link */
.item .cover{cursor:pointer}
.name a{color:inherit}
.item:hover .name a{color:var(--acc)}

/* ── four across, always ─────────────────────────────────────────────────── */
/* The catalogue's grid is auto-fill, which gives five at 1180px. Here the count is
   fixed so rows stay predictable and the related strip fills exactly. */
.grid{grid-template-columns:repeat(4,1fr)}
@media(max-width:900px){.grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:640px){.grid{grid-template-columns:repeat(2,1fr);gap:var(--s-2)}}

/* ── category filter ─────────────────────────────────────────────────────── */
/* .item is display:flex, which beats the UA's [hidden]{display:none}, so hiding a
   filtered-out card needs saying explicitly. */
.item[hidden]{display:none}
.toolbar{margin:0 0 var(--s-4)}
.no-match{padding:var(--s-7) 0 var(--s-2);font-size:var(--t-body);font-weight:600;color:var(--ink2);text-align:center}
.no-match[hidden]{display:none}
.no-match button{font-size:var(--t-body);font-weight:700;color:var(--acc);text-decoration:underline;
  text-underline-offset:2px;padding:0}

/* ── Instagram ───────────────────────────────────────────────────────────── */
.ig{display:inline-flex;align-items:center;gap:var(--s-2)}
.ig svg{width:15px;height:15px;fill:currentColor;flex-shrink:0}

/* the third hero CTA carries an icon, so it needs the gap the other two do not */
.ig-cta{gap:var(--s-2)}
.ig-cta svg{width:15px;height:15px;fill:currentColor;flex-shrink:0}

/* <picture> wraps every product photo so a WebP can be offered with the JPEG as
   fallback. It is display:inline by default, which would make it — not the <img> —
   the flex item in the thumbnail strip. display:contents removes it from layout so
   the image stays the flex child and the existing sizing rules keep applying. */
.pd-thumbs picture{display:contents}


/* ═══ Mobile navigation ══════════════════════════════════════════════════════
   page.html hides .nav-links below 900px, which is right for the single-file
   catalogue: its nav is two items and a chip strip sits underneath carrying the
   categories. The generated site has neither, so that rule left a phone with no
   category navigation at all — just the logo and the Shopee button. These rules
   are in site.css rather than page.html so only the site gets them. */
@media(max-width:900px){
  .nav{height:auto}
  .nav-in{flex-wrap:wrap;height:auto;padding-top:var(--s-1);gap:var(--s-1)}
  /* Wrapped, not scrolled. A horizontal strip always hides some of the range, and
     the fade at its edge was too quiet to read as "there is more" — the six
     collections are the whole proposition, so they are all on screen at once. */
  .nav-links{display:flex;order:3;flex:0 0 100%;flex-wrap:wrap;
    margin:0;padding-bottom:var(--s-1);gap:var(--s-1) 0;overflow:visible;
    -webkit-mask-image:none;mask-image:none}
  /* 44px is the tap-target floor; these were 31px. Height comes from padding so
     the label stays vertically centred. */
  .nav-links a{white-space:nowrap;padding:var(--s-2) var(--s-3) var(--s-2) 0;font-size:var(--t-sm);
    display:inline-flex;align-items:center;min-height:40px}
  /* The desktop underline is drawn inside an 8px-radius link, which reads as a box
     once the row wraps. On a phone the current section is marked in brand green
     instead — no geometry to go wrong across two rows. */
  .nav-links a[aria-current="page"]{box-shadow:none;color:var(--acc);font-weight:800}
  .nav-links a:first-child{padding-left:0}
}
@media(max-width:400px){
  .nav-links a{font-size:var(--t-xs);padding-right:var(--s-2)}
  .nav-shop{font-size:var(--t-xs);padding:var(--s-2) var(--s-3)}
}

/* ═══ Nav hierarchy ══════════════════════════════════════════════════════════
   Seven links styled identically read as one flat list, but they are not one
   kind of thing: six are collections and About is a page. And nothing marked the
   current section, so standing on /kitchen-baskets/ looked the same as standing
   anywhere else — the nav gave you no sense of place. */

/* Where you are. Nothing is drawn: the current item goes to full ink at 800 and
   every sibling drops back, so the selection reads by contrast rather than by
   decoration. The previous version painted a 2px rule as an inset shadow, which
   followed the link's 8px radius and hooked upward at both ends. Any drawn marker
   inside a rounded box has that problem; not drawing one removes the class of bug,
   and it matches the mobile nav, which already distinguishes by colour alone. */
.nav-links a{color:var(--ink3)}
.nav-links a:hover{color:var(--ink)}
.nav-links a[aria-current="page"]{color:var(--ink);font-weight:800;box-shadow:none}

/* About is not a collection. A hairline sets it apart from the six and the
   lighter tone stops it competing with them. */
.nav-about{color:var(--ink3);margin-left:var(--s-2);padding-left:var(--s-4);
  border-left:1px solid var(--hair);border-radius:0 8px 8px 0}
.nav-about:hover{color:var(--ink)}

@media(max-width:900px){
  .nav-about{margin-left:var(--s-1);padding-left:var(--s-4);border-radius:0}
  /* Desktop and mobile now use the same treatment, so this only needs to survive
     the drawer rules above it. */
  .nav-links a[aria-current="page"]{box-shadow:none;color:var(--ink);font-weight:800}
}

/* ═══ Lead paragraphs ════════════════════════════════════════════════════════
   page.html sets .lead at clamp(17px,1.7vw,21px), which is right for the
   single-file catalogue where one lead sits above a grid. On the site the same
   size pushed the homepage intro and the about copy down the page for no gain in
   readability: body copy is 17px, so a lead at 21px was competing with the
   headings rather than supporting them. Scoped here so the catalogue keeps its
   own scale. */
.lead{font-size:var(--t-sm);line-height:1.55}
.home .sec .lead{margin-bottom:var(--s-4)}

/* ═══ Mobile drawer ══════════════════════════════════════════════════════════
   Seven links wrapped across two rows cost 130px of sticky height, about a sixth
   of a phone screen, for navigation most visitors use once. The burger gives that
   back and lets the two kinds of destination be labelled rather than merely
   spaced: Collections, then More.

   `has-drawer` is added by the script in foot(). Without JavaScript the class is
   never set, the burger stays hidden and the links render inline and wrapped as
   before, so the range is reachable either way. */
.nav-burger{display:none;align-items:center;justify-content:center;
  width:40px;height:40px;margin-left:auto;border-radius:9px;color:var(--ink2);
  background:none;border:0;cursor:pointer;flex-shrink:0}
.nav-burger svg{width:21px;height:21px;fill:none;stroke:currentColor;
  stroke-width:1.9;stroke-linecap:round}
.nav-burger:hover{color:var(--ink);background:rgba(0,0,0,.045)}

@media(min-width:901px){ .nav-burger,.drawer{display:none !important} }

@media(max-width:900px){
  .has-drawer .nav-burger{display:inline-flex}
  .has-drawer .nav-links{display:none}
  /* the bar goes back to one row once the links are in the drawer */
  .has-drawer .nav{height:var(--nav-h)}
  .has-drawer .nav-in{flex-wrap:nowrap;height:var(--nav-h);padding-top:0}
  .has-drawer .nav-shop{margin-left:var(--s-1)}
}

.drawer{position:fixed;inset:0;z-index:200;background:rgba(11,11,13,.45);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.drawer[hidden]{display:none}
.drawer-panel{position:absolute;top:0;right:0;bottom:0;width:min(310px,84vw);
  background:var(--card);box-shadow:-16px 0 44px rgba(11,11,13,.22);
  padding:var(--s-4) var(--s-4) var(--s-5);overflow-y:auto;display:flex;flex-direction:column;
  animation:drawer-in .18s ease-out}
@keyframes drawer-in{from{transform:translateX(100%)}to{transform:none}}
@media(prefers-reduced-motion:reduce){.drawer-panel{animation:none}}

.drawer-top{display:flex;align-items:center;justify-content:space-between;
  margin-bottom:var(--s-4)}
.drawer-brand{font-weight:800;letter-spacing:-.02em;color:var(--acc);font-size:var(--t-xl)}
.drawer-x{width:40px;height:40px;margin-right:-8px;border:0;background:none;
  color:var(--ink2);cursor:pointer;border-radius:9px;
  display:inline-flex;align-items:center;justify-content:center}
.drawer-x svg{width:20px;height:20px;fill:none;stroke:currentColor;
  stroke-width:1.9;stroke-linecap:round}
.drawer-x:hover{color:var(--ink);background:rgba(0,0,0,.045)}

/* The labels are the point: they say which links are the range and which are not,
   which spacing alone never did. */
.drawer-h{font-size:var(--t-xs);font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink3);margin:0 0 var(--s-1);padding-left:var(--s-1)}
.drawer-nav{display:flex;flex-direction:column;margin-bottom:var(--s-5)}
.drawer-nav a{display:flex;align-items:center;min-height:46px;padding:var(--s-1) var(--s-2);
  margin-inline:-10px;border-radius:10px;font-size:var(--t-md);font-weight:600;
  color:var(--ink);border-bottom:1px solid var(--hair-soft)}
.drawer-nav a:last-child{border-bottom:0}
.drawer-nav a:hover,.drawer-nav a:focus-visible{background:var(--tint)}
.drawer-nav a[aria-current="page"]{color:var(--acc);font-weight:800}
.drawer-more a{font-weight:600;color:var(--ink2)}
.drawer-more{margin-bottom:0}

/* ═══ Cross-sell strip ═══════════════════════════════════════════════════════
   A horizontal rail of medium-to-high value products from the collections that
   belong to the same job. Scrolls with CSS scroll-snap and no script, so every
   card is a real link in the HTML rather than something a crawler has to run
   JavaScript to reach. */
.strip{margin:var(--s-6) 0;padding-top:var(--s-6);
  border-top:1px solid var(--hair)}
.strip-hd{margin-bottom:var(--s-4)}
.strip-hd h2{font-size:var(--t-h2);margin-bottom:var(--s-1)}
.strip-hd p{font-size:var(--t-sm);color:var(--ink2);max-width:62ch;line-height:1.5}

.strip-rail{list-style:none;display:flex;gap:var(--s-3);overflow-x:auto;
  scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;
  scrollbar-width:none;padding:var(--s-1) var(--s-1) var(--s-1)}
.strip-rail::-webkit-scrollbar{display:none}
/* full-bleed on a phone so a card is never sliced by the page gutter */
@media(max-width:600px){
  .strip-rail{margin-inline:-16px;padding-inline:var(--s-4);scroll-padding-left:var(--s-4)}
}

.strip-item{flex:0 0 172px;scroll-snap-align:start}
@media(min-width:601px){.strip-item{flex-basis:194px}}
.strip-item a{display:flex;flex-direction:column;height:100%;background:var(--card);
  border:1px solid var(--hair-soft);border-radius:var(--r);padding:var(--s-3);
  transition:transform .18s,box-shadow .18s}
.strip-item a:hover{transform:translateY(-4px);box-shadow:0 12px 30px rgba(11,11,13,.12)}
.strip-img{position:relative;aspect-ratio:1;margin-bottom:var(--s-3)}
.strip-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:5%}
.strip-kick{font-size:var(--t-xs);font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink3);margin-bottom:var(--s-1)}
.strip-name{font-size:var(--t-sm);font-weight:700;line-height:1.32;letter-spacing:-.015em;
  flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.strip-cost{font-size:var(--t-md);font-weight:800;margin-top:var(--s-2)}

/* ═══ Shopee buttons ═════════════════════════════════════════════════════════
   Shopee's own orange is #EE4D2D, which carries white text at only 3.66:1 and
   fails the 4.5:1 this site holds everywhere else. #DF3412 is that orange
   darkened 15% at the same hue and saturation: 4.53:1, and near-indistinguishable
   unless the two are side by side.

   This overrides page.html, where the buttons take the ELKY green and the note on
   --shopee says the orange is a recognition cue and never a large field. That was
   a deliberate call to keep the page ELKY's; using Shopee's own colour on the buy
   button is a deliberate reversal of it. The catalogue keeps the green. */
:root{ --shopee-btn:#DF3412; --shopee-btn-d:#BE2C0F }
.nav-shop{background:var(--shopee-btn)}
.nav-shop:hover{background:var(--shopee-btn-d)}
.btn-shopee,.pd-buy .btn-shopee{background:var(--shopee-btn);border-color:var(--shopee-btn)}
.btn-shopee:hover,.pd-buy .btn-shopee:hover{background:var(--shopee-btn-d);border-color:var(--shopee-btn-d)}

/* ═══ Hero headline and CTAs ═════════════════════════════════════════════════
   page.html sets the headline at up to 70px and the buttons at 15px/26px padding
   with .13em tracking on uppercase text. That combination is wide: three buttons
   came to 654px on a desktop and, once the 480px rule gave each one a full row,
   176px of a phone screen. The hero was taking 56% of a 375x812 viewport before
   any product was visible.

   The type is unchanged in character: still Playfair Display italic, which is the
   thing that reads as interior design rather than builders' merchant. It is just
   smaller, which also lets "Leave the installation to us." sit on one line at
   375px instead of wrapping to two.

   Scoped to site.css, so the single-file catalogue keeps its own scale. */
.hero h1{font-size:var(--t-hero);letter-spacing:-.015em;line-height:1.04}
.hero-cta{gap:var(--s-2);margin-top:var(--sr-2)}
.btn-hero{font-size:var(--t-xs);letter-spacing:.06em;padding:var(--s-2) var(--s-4);border-radius:999px;gap:var(--s-2)}
.btn-hero svg{width:14px;height:14px}

/* The buy button carries Shopee's colour here as it does elsewhere on the site.
   It stays second: the range comes before the checkout, which is the whole point
   of having 166 indexed pages. */
.btn-hero.is-shopee{background:var(--shopee-btn);border-color:var(--shopee-btn);color:#fff}
.btn-hero.is-shopee:hover{background:var(--shopee-btn-d);border-color:var(--shopee-btn-d)}

/* On a phone the primary keeps its own row and the other two share the next one.
   Three full-width rows was 176px; this is 106px, and no label had to be cut down
   to get there - "Follow for a discount" states an offer, "Follow" asks a favour. */
@media(max-width:480px){
  .hero-cta a{flex:1 1 calc(50% - 5px);justify-content:center}
  .hero-cta a:first-child{flex:1 1 100%}
}

/* Shopee's mark is a filled path, where every other icon on the site is stroked,
   so it has to opt out of the stroke rules rather than inherit them. */
/* .nav-shop svg and .btn-hero svg are both class+type, which outranks a bare class,
   so the opt-out has to match their specificity rather than rely on source order. */
.shopee-mark,
.nav-shop .shopee-mark,
.btn-hero .shopee-mark,
.btn-shopee .shopee-mark,
.drawer-nav .shopee-mark{fill:currentColor;stroke:none;flex-shrink:0}
.nav-shop .shopee-mark{width:15px;height:15px}
.btn-hero .shopee-mark{width:14px;height:14px}
.btn-shopee .shopee-mark{width:16px;height:16px;margin-right:var(--s-2);vertical-align:-3px}


/* ═══ Category header ════════════════════════════════════════════════════════
   The first product sat 365px down on a 1024x768 desktop, 48% of the viewport,
   behind a nav, a breadcrumb, a heading, a blurb, a price line and a full-width
   toolbar. The search and sort controls do not need a row of their own: they go
   beside the heading, which is narrow anyway at max-width 66ch, so the space to
   its right was empty.

   That plus trimmed padding puts the first product at 281px, 37%. The heading
   keeps its size deliberately. It carries the page's keyword phrase and dropping
   it to h2 would have bought another 37px at the cost of the page's own hierarchy.

   The toolbar used to sit in a second column beside the heading, which saved about
   90px of height and cost the search box its own text: squeezed into what was left of
   a 1440px row it had 204px of usable width against the 294px the longest placeholder
   needs, so "Search kitchen baskets & pull-out storage" was cut off at "& p". A search
   field that cannot show what it searches is not worth 90px. It now runs full width on
   its own row under the heading, with the field, the filters and the count in that one
   row. */

/* Instagram's mark is a filled path like Shopee's, so it opts out of the stroke
   rules rather than inheriting them. */
.ig-mark,.ig .ig-mark,.ig-cta .ig-mark{fill:currentColor;stroke:none;flex-shrink:0}
/* Brand pink in the footer, where it sits on the light ground at 3.50:1 and clears
   the 3:1 a non-text icon needs. Not on the hero: the button is a ghost over a
   photograph, and the pink measures 1.29:1 against the brightest point behind it,
   so there the mark stays white with the label. */
.ig .ig-mark{color:#FF0069}

/* ═══ Lifestyle banner ═══════════════════════════════════════════════════════
   Photo one side, copy the other. See banner() in site.js for why this shape
   rather than a full-bleed band. Stacks on a phone with the photo on top. */
.bnr{display:grid;grid-template-columns:1fr 1fr;background:var(--card);
  border-radius:var(--r);overflow:hidden;margin:var(--sr-4) 0}
.bnr-ph{position:relative;min-height:250px}
.bnr-ph picture{display:contents}
.bnr-ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.bnr-tx{padding:var(--sr-3);display:flex;flex-direction:column;justify-content:center}
.bnr-tx h2{font-size:var(--t-h2);margin-bottom:var(--s-2)}
.bnr-tx p{font-size:var(--t-sm);color:var(--ink2);line-height:1.55;
  margin-bottom:var(--s-4);max-width:46ch}
.bnr-go{align-self:start;background:var(--acc);color:#fff;font-size:var(--t-xs);
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:var(--s-3) var(--s-4);border-radius:999px;transition:background .15s}
.bnr-go:hover{background:var(--acc-d)}
@media(max-width:700px){
  .bnr{grid-template-columns:1fr}
  .bnr-ph{min-height:200px;aspect-ratio:16/10}
}

/* ═══ Hero pan ═══════════════════════════════════════════════════════════════
   The hero drifts slowly across itself. One photograph, no extra bytes.

   This replaced a three-image crossfade, which read as a slideshow of nearly
   identical dark cabinets — the cuts drew attention to themselves and to how
   alike the frames were. A pan has no cuts to notice.

   Cost is zero: `transform` on a single element is composited on the GPU, so
   nothing re-lays-out and nothing re-paints for the life of the animation, and
   the image is the one the page was already loading. The earlier crossfade cost
   47KB of alternates; the GIF and animated-WebP versions measured 17.6MB and
   16.1MB.

   The baseline is scale(1.06), not scale(1) — the drift needs overflow to move
   into, and at 1 the translate would pull an edge into frame. 1.06 gives 3% of
   slack on each side, and the translate stays inside 1.2% of it. `alternate`
   reverses rather than restarting, so it never snaps back to the first frame.

   44s is deliberately slower than it feels like it should be. Motion under a
   headline competes with the headline; at this speed it reads as depth rather
   than as something happening. prefers-reduced-motion holds it still. */
.hero-bg{animation:heroPan 44s ease-in-out infinite alternate;
  transform-origin:center center}
/* Constant scale, not a zoom. The scale is there only to give the translate somewhere
   to move: 1.03 leaves 1.5% of overflow on each side and the drift stays inside 1.2% of
   it. It used to run 1.06 to 1.12, which was pure cost - on a 1920px screen the hero is
   already upscaled 1.14x just to cover the box, and the zoom carried that to 1.30x. A
   photograph drawn a third larger than its own pixels is what "stretched" looks like. */
@keyframes heroPan{
  from{transform:scale(1.03) translate3d(-1.2%,.6%,0)}
  to{transform:scale(1.03) translate3d(1.2%,-.6%,0)}
}
}
@media(prefers-reduced-motion:reduce){ .hero-bg{animation:none;transform:none} }

/* The hero is centre-cropped, and on a phone it keeps only the middle 46% of the
   frame — which lands just right of the pull-out and clips it at the edge, leaving
   plain cabinetry as the whole picture. Pulling the crop window left to 40% keeps
   the window at 22%-68% of the image instead of 27%-73%, which puts the open unit
   fully in shot. Desktop is wide enough not to need it. */
@media(max-width:700px){ .hero-bg{object-position:40% center} }

/* ═══ Hero intro ═════════════════════════════════════════════════════════════
   6.5 seconds across two kitchens with the photograph left bright, then the scrim
   and the copy arrive. Hovering brings them early without stopping the pan.

   It is opt-in from script, and the state it falls back to is the finished one: no
   class means the scrim is painted and the copy is up, which is the hero as it was
   before any of this. Nothing that matters waits on JavaScript.

   The copy has to hide, it is not a stylistic choice. White type over these kitchens
   with no veil measures 1.4:1 against the brightest fifth of the pixels behind it -
   the headline is effectively not there. With the scrim it is 7.5:1.

   Two classes: hero-seq runs the frame for the full 6.5s, hero-lit brings the scrim
   and copy in. Separating them is what lets a hover at two seconds darken the banner
   while the pan carries on underneath, rather than cutting to the end. */
.hero-frame{position:absolute;inset:0;display:block;opacity:0;z-index:-2}
.hero-frame img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center}
.hero::after{transition:opacity 1.1s ease}
.hero-copy{transition:opacity .9s ease,transform .9s ease}
.hero-seq::after{opacity:0}
.hero-seq .hero-copy{opacity:0;transform:translateY(12px)}
.hero-seq.hero-lit::after{opacity:1}
.hero-seq.hero-lit .hero-copy{opacity:1;transform:none}
/* Three kitchens over 9.5s. Holds are about 2.2s and the crossfades a second, which
   is roughly twice what they were when this ran four frames in 12s.

   The set was cut on measured similarity, not taste. Six photographs blurred into each
   other - two pairs scored 0.62 and 0.67 on a combined colour-and-histogram distance,
   against 1.15 for the closest pair in what is kept - so it is a bright handleless
   kitchen, a mechanism in close-up and a sage-green traditional one. Three that read as
   three, and 156KB rather than 305KB.

   The fades overlap, and that was the part that was wrong rather than merely quick.
   Each frame used to fade out to nothing before the next began, so for about a second
   in the middle of every transition the base photograph showed through and the hero
   blinked back to the first kitchen. An outgoing frame now holds at opacity 1 until the
   incoming one has covered it, then drops to 0 in the following 1% while hidden behind
   it. Only the last fades for real, because the base underneath is what it fades to.

   Neither appears anywhere else on the landing page - the banners are a separate set -
   so scrolling past the hero never shows the same kitchen twice. */
.hero-seq .hero-frame{animation-duration:9.5s;animation-timing-function:linear;
  animation-fill-mode:both}
.hero-seq .hero-frame img{animation:heroFramePan 9.5s ease-in-out both}
.hero-seq .hero-frame-1{animation-name:heroF1}
.hero-seq .hero-frame-2{animation-name:heroF2}
@keyframes heroF1{0%,23%{opacity:0} 34%,67%{opacity:1} 68%,100%{opacity:0}}
@keyframes heroF2{0%,57%{opacity:0} 67%,90%{opacity:1} 100%{opacity:0}}
@keyframes heroFramePan{
  from{transform:scale(1.03) translate3d(1.2%,-.5%,0)}
  to{transform:scale(1.03) translate3d(-1.2%,.5%,0)}
}
}
}
}
@media(prefers-reduced-motion:reduce){ .hero-frame{display:none} }

/* ═══ Site search ════════════════════════════════════════════════════════════
   A hybrid: the field expands in place inside the nav the way the inline version
   did, and the results get the roomier panel the overlay version had. What it
   deliberately does not do is become a screen. There is no backdrop, nothing is
   dimmed, the page stays visible and scrollable underneath, and on a phone the
   panel is still a panel rather than a takeover - it is capped at 62vh so there
   is always page showing beneath it.

   The whole thing is opt-in from script: .has-search is added by the JS, and
   without it the button is not shown and the field is not rendered, so nothing
   here can leave a dead control on the page. */
/* margin-left:auto lives here rather than on the burger. The burger had it, which
   made the burger the thing that absorbed the free space - and since the search
   button sits before it in the source, search was left stranded beside the logo
   while everything else sat on the right. Whichever control comes first in the
   right-hand group is the one that should carry the auto margin. */
.nav-search{display:none;align-items:center;justify-content:center;
  width:40px;height:40px;flex-shrink:0;border-radius:99px;border:1px solid var(--hair);
  background:var(--card);color:var(--ink2);cursor:pointer;transition:border-color .15s,color .15s,background .15s}
.has-search .nav-search{display:inline-flex;margin-left:auto}
/* Exactly one auto margin in the group, or the free space is split between them and
   the icon floats in the middle of the bar - two autos put 68px between search and
   the Shopee button on a 1440px screen. Scoped to .has-search so that without the
   script .nav-shop keeps the auto margin and still sits right. */
.has-search .nav-burger{margin-left:0}
.has-search .nav-shop{margin-left:var(--s-2)}
.nav-search:hover{border-color:var(--ink3);color:var(--ink)}
/* Bigger lens, shorter body, thicker stroke. The old glyph was a 7px circle with a
   thin 2px tail at 17px, which at a glance read as a generic dot rather than as a
   magnifier - the handle has to be visibly a handle for the shape to say "search". */
.nav-search svg{width:19px;height:19px;stroke:currentColor;stroke-width:2.2;fill:none;
  stroke-linecap:round;stroke-linejoin:round}

/* Capped rather than free-growing. Open on a 1440px screen the field used to take
   the whole bar, which made both the box and the panel under it wider than anything
   they had to hold. 520px is the same ceiling the category toolbar uses. */
.nav-find{display:none;position:relative;flex:1 1 420px;max-width:520px;min-width:0;
  margin-inline:var(--s-3);margin-right:auto}
.nav-open .nav-find{display:block}
.nav-open .nav-links{display:none}
.nav-open .nav-search{display:none}
.nav-find-i{position:absolute;left:14px;top:50%;transform:translateY(-50%);width:16px;height:16px;
  stroke:var(--ink3);stroke-width:2;fill:none;stroke-linecap:round;pointer-events:none}
.nav-find input{width:100%;border:1px solid var(--hair);border-radius:99px;
  padding:var(--s-2) 42px var(--s-2) 40px;background:var(--card);
  font-size:var(--t-md);font-weight:500;outline:none;transition:border-color .15s,box-shadow .15s}
.nav-find input:focus{border-color:var(--ink3);box-shadow:0 0 0 4px rgba(11,11,13,.07)}
/* type="search" draws its own clear button in WebKit, which sat next to ours: two
   crosses a few pixels apart doing different things - one wipes the text, one shuts
   the search. The type is kept for the semantics and the native control is hidden. */
.nav-find input::-webkit-search-cancel-button,
.nav-find input::-webkit-search-decoration{-webkit-appearance:none;appearance:none}
.nav-find-x{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:30px;height:30px;display:flex;align-items:center;justify-content:center;
  border:0;background:none;color:var(--ink3);cursor:pointer;border-radius:99px}
.nav-find-x:hover{color:var(--ink)}
.nav-find-x svg{width:15px;height:15px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round}

/* Anchored to the field, not to the nav and not to the viewport. It sits inside
   .nav-find, so left:0/right:0 resolve to exactly the width of the box you typed
   into and the results line up under it. Spanning the whole bar made a panel that
   had nothing to do with the control that opened it, and left eight short rows
   stranded across 1440px.

   It still stops well short of the fold, so the page is never replaced by it. */
.sres{position:absolute;left:0;right:0;top:calc(100% + var(--s-2));z-index:60;
  background:var(--card);border:1px solid var(--hair);border-radius:12px;
  box-shadow:0 18px 44px rgba(0,0,0,.16);max-height:62vh;overflow:auto;
  overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.sres[hidden]{display:none}
.sres-in{padding:var(--s-1) 0 var(--s-2)}
.sres-g{font-size:var(--t-xs);font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink3);padding:var(--s-3) var(--s-4) var(--s-2)}
.sres a{display:flex;align-items:center;gap:var(--s-3);padding:var(--s-2) var(--s-4);
  text-decoration:none;color:inherit;min-height:44px}
.sres a:hover,.sres a.on{background:var(--bg)}
.sres a.on{outline:2px solid var(--acc);outline-offset:-2px}
.sres img{width:42px;height:42px;object-fit:contain;background:var(--bg);border-radius:7px;flex-shrink:0}
.sres .sres-n{width:42px;height:42px;border-radius:7px;background:var(--acc);color:#fff;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;font-size:var(--t-xs);font-weight:800}
.sres-t{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow:hidden}
.sres-t b{font-size:var(--t-sm);font-weight:600;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sres-t span{font-size:var(--t-xs);color:var(--ink3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sres-p{flex:0 0 auto;margin-left:auto;padding-left:var(--s-3);
  font-size:var(--t-sm);font-weight:700;color:var(--ink)}
.sres mark{background:#FCE8A8;color:inherit;border-radius:2px}
.sres-none{padding:var(--s-5) var(--s-4);font-size:var(--t-sm);color:var(--ink2)}
.sres-k{padding:var(--s-2) var(--s-4) 0;margin-top:var(--s-2);
  border-top:1px solid var(--hair-soft);font-size:var(--t-xs);color:var(--ink3)}

/* On a phone the field takes the bar and the logo steps aside, but the results
   are still a panel under the nav with the page showing below. */
@media(max-width:700px){
  .nav-open .mark{display:none}
  .nav-open .nav-shop{display:none}
  .nav-open .nav-burger{display:none}
  .nav-find{margin-inline:0;flex:1 1 auto;max-width:none}
  /* beside the burger, so it matches the burger: same box, no ring around it. A
     bordered circle next to a bare icon reads as two different kinds of control. */
  .nav-search{border:0;background:none;border-radius:9px}
  .nav-search:hover{background:rgba(0,0,0,.045)}
  .sres-k{display:none}
}
@media(prefers-reduced-motion:no-preference){
  .sres{animation:sresIn .16s ease-out}
  @keyframes sresIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
}

/* ── Search: collection rows ──────────────────────────────────────────────────
   A collection is not a product and should not look like one. The row used to
   carry a green square with the product count in it, which styled a number like
   a photograph and then repeated that number in the line directly underneath.

   It now shows three of the things inside, overlapped the way a stack of cards
   is, which reads as "a group of things" at a glance rather than "one thing".
   The sub-line answers the two questions a count alone does not: how much is in
   here, and what does the cheapest one cost. "Browse" says out loud that this
   goes to a listing and not to a product page. */
.sres-c{align-items:center}
.sres-c:hover,.sres-c.on{background:var(--bg)}
.sres-stack{display:flex;flex-shrink:0;padding-right:var(--s-2)}
.sres-stack img{width:38px;height:38px;object-fit:contain;background:var(--card);
  border:1px solid var(--hair-soft);border-radius:8px;position:relative;flex-shrink:0}
.sres-stack img + img{margin-left:-14px}
.sres-c .sres-t b{font-weight:700}
.sres-go{flex:0 0 auto;margin-left:auto;padding-left:var(--s-3);display:inline-flex;
  align-items:center;gap:var(--s-1);font-size:var(--t-xs);font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;color:var(--acc)}
.sres-go svg{width:14px;height:14px;stroke:currentColor;stroke-width:2.2;fill:none;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .15s}
.sres-c:hover .sres-go svg,.sres-c.on .sres-go svg{transform:translateX(3px)}
/* the word is the first thing to go when the panel is narrow; the arrow still reads */
.sres-go i{font-style:normal}
@media(max-width:480px){ .sres-go i{display:none} .sres-go svg{width:16px;height:16px} }

/* ═══ Product page ═══════════════════════════════════════════════════════════
   The gallery gets a thumbnail rail beside it instead of one stranded square
   under a very tall image, and the column beside it stops ending in empty
   space: where the sizes can be told apart they become the thing you pick,
   and the rest of the time three plain facts fill it.

   Below, the specification table no longer stretches. It was width:100% under
   a 1180px page, which spread five short columns across the whole width and
   put an inch of nothing between "Depth" and "461mm". It sizes to its own
   contents now and shares the row with the description, so the width is used
   rather than stretched. */
.pd-media{display:grid;grid-template-columns:76px minmax(0,1fr);gap:var(--s-3);align-items:start}
.pd-thumbs{display:flex;flex-direction:column;gap:var(--s-2);margin:0}
.pd-thumbs img{width:76px;height:76px;object-fit:contain;background:var(--bg);
  border:1.5px solid var(--hair);border-radius:9px}
.pd-stage{background:var(--bg);border-radius:12px;overflow:hidden}
.pd-stage img,.pd-hero{width:100%;height:auto;display:block}

/* The size picker is radio buttons and labels, so it works with no script at
   all - the chosen size and its dimensions are plain CSS sibling state. */
.pd-pick{border:0;padding:0;margin:0 0 var(--s-4);display:flex;flex-wrap:wrap;gap:var(--s-2)}
.pd-pick legend{font-size:var(--t-xs);font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3);margin-bottom:var(--s-2)}
.pd-r{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.pd-chip{flex:1 1 0;min-width:92px;border:1.5px solid var(--hair);border-radius:10px;
  padding:var(--s-2);text-align:center;cursor:pointer;transition:border-color .12s,background .12s}
.pd-chip b{display:block;font-size:var(--t-md);font-weight:800;color:var(--ink)}
.pd-chip span{display:block;font-size:var(--t-xs);color:var(--ink3)}
.pd-chip:hover{border-color:var(--ink3)}
.pd-r:checked + .pd-chip{border-color:var(--acc);background:rgba(71,104,59,.07)}
.pd-r:focus-visible + .pd-chip{outline:2px solid var(--acc);outline-offset:2px}
.pd-fit{flex:0 0 100%;display:none;font-size:var(--t-sm);color:var(--ink2);margin-top:var(--s-1)}
.pd-fit b{color:var(--ink)}
.pd-sku{font-variant-numeric:tabular-nums;color:var(--ink3)}
#pdsz0:checked ~ .pd-fit:nth-of-type(1),
#pdsz1:checked ~ .pd-fit:nth-of-type(2),
#pdsz2:checked ~ .pd-fit:nth-of-type(3),
#pdsz3:checked ~ .pd-fit:nth-of-type(4),
#pdsz4:checked ~ .pd-fit:nth-of-type(5),
#pdsz5:checked ~ .pd-fit:nth-of-type(6){display:block}

.pd-facts{list-style:none;margin:0 0 var(--s-4);display:flex;flex-direction:column;gap:var(--s-2)}
.pd-facts li{position:relative;padding-left:var(--s-5);font-size:var(--t-sm);color:var(--ink2)}
.pd-facts li::before{content:"";position:absolute;left:0;top:6px;width:13px;height:8px;
  border-left:2.4px solid var(--acc);border-bottom:2.4px solid var(--acc);transform:rotate(-45deg)}

.pd-below{display:grid;grid-template-columns:auto minmax(280px,540px);gap:var(--sr-3);
  justify-content:start;align-items:start;margin-top:var(--sr-3)}
.pd-below h2{font-size:var(--t-h2);margin-bottom:var(--s-3)}
.pd-below p{max-width:60ch}
.pd-tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
.pd-table{width:auto;max-width:100%;border-collapse:collapse;font-size:var(--t-sm)}
.pd-table th,.pd-table td{text-align:left;padding:var(--s-2) var(--s-4) var(--s-2) 0;
  border-bottom:1px solid var(--hair-soft);white-space:nowrap}
.pd-table th{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.06em;
  color:var(--ink3);font-weight:700}
.pd-table td:first-child{color:var(--ink2)}

@media(max-width:700px){
  .pd-media{grid-template-columns:minmax(0,1fr)}
  .pd-thumbs{flex-direction:row;order:2;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .pd-thumbs img{width:64px;height:64px;flex-shrink:0}
  .pd-stage{order:1}
  .pd-below{grid-template-columns:minmax(0,1fr);gap:var(--sr-2)}
}

/* ── Product page: the gap, and the gallery ───────────────────────────────────
   .pd-spec and .pd-about each carry a border-top and padding-top of their own,
   which was right when they were stacked sections and wrong the moment they
   became two columns of one band: the rule and the space were drawn twice, on
   top of the band's own margin. One border on the band, none on the children. */
.pd-below{border-top:1px solid var(--hair-soft);padding-top:var(--s-5);margin-top:var(--sr-1)}
/* A portrait photograph in a 430px column is 538px tall against an info column of
   about 487, and the difference lands as blank space under the buy button where it
   reads as a hole rather than as rhythm. Capping the stage brings the two columns
   within a few pixels of each other and stops the image growing without limit on a
   wide screen. */
/* One frame, not two. The stage had a grey card and the image its own white one
   inside it, so the product sat inside a box inside a box and came out filling
   67% of a 518px column. The stage is now just a centring box with no surface of
   its own, the image keeps the white card, and the inner padding drops from 5%
   to 3%.

   The cap goes up as well. It was clamp(300px,48vh,500px), which was tuned to
   close a gap that turned out to be a doubled border rather than the picture,
   and it made the photograph smaller than it needs to be. A portrait shot cannot
   fill a wide column without becoming very tall, so this is the compromise: big
   enough to read, short enough that the column beside it is not left hanging. */
.pd-stage{max-height:clamp(360px,62vh,600px);display:grid;place-items:center;
  background:none;border-radius:0;overflow:visible}
.pd-stage .pd-shot{max-height:100%;display:none}
.pd-stage .pd-shot:first-child{display:block}
.pd-stage img,.pd-hero{max-height:clamp(360px,62vh,600px);width:auto;max-width:100%;
  height:auto;object-fit:contain;display:block;padding:3%}

/* The band sits inside the product page, not at the top level of it. At --t-h2
   its headings were the same size the homepage gives a whole section, which read
   as louder than the table underneath them. */
.pd-below h2{font-size:var(--t-xl)}
.pd-below .pd-spec,.pd-below .pd-about{border-top:0;padding-top:0;margin-top:0}

/* Thumbnails that actually do something. Radio inputs and labels again, so the
   gallery works with no script: the checked input shows its own shot and marks
   its own thumbnail. They are position:absolute so they take no grid cell. */
.pd-ir{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.pd-th{display:block;cursor:pointer;border:1.5px solid var(--hair);border-radius:9px;
  overflow:hidden;background:var(--bg);transition:border-color .12s}
.pd-th:hover{border-color:var(--ink3)}
.pd-th img{display:block;width:100%;height:100%;object-fit:contain}
.pd-shot{display:none}
.pd-shot:first-child{display:block}
#pdimg0:checked ~ .pd-stage .pd-shot:nth-child(1),
#pdimg1:checked ~ .pd-stage .pd-shot:nth-child(2),
#pdimg2:checked ~ .pd-stage .pd-shot:nth-child(3),
#pdimg3:checked ~ .pd-stage .pd-shot:nth-child(4),
#pdimg4:checked ~ .pd-stage .pd-shot:nth-child(5){display:block}
#pdimg1:checked ~ .pd-stage .pd-shot:nth-child(1),
#pdimg2:checked ~ .pd-stage .pd-shot:nth-child(1),
#pdimg3:checked ~ .pd-stage .pd-shot:nth-child(1),
#pdimg4:checked ~ .pd-stage .pd-shot:nth-child(1){display:none}
#pdimg0:checked ~ .pd-thumbs .pd-th:nth-child(1),
#pdimg1:checked ~ .pd-thumbs .pd-th:nth-child(2),
#pdimg2:checked ~ .pd-thumbs .pd-th:nth-child(3),
#pdimg3:checked ~ .pd-thumbs .pd-th:nth-child(4),
#pdimg4:checked ~ .pd-thumbs .pd-th:nth-child(5){border-color:var(--ink);border-width:2px}
.pd-ir:focus-visible ~ .pd-thumbs .pd-th{outline:0}
.pd-media .pd-thumbs{margin-top:0;flex-wrap:nowrap}
.pd-media .pd-thumbs img{width:auto;height:auto;padding:var(--s-1)}
.pd-media .pd-th{width:76px;height:76px;flex-shrink:0}
@media(max-width:700px){ .pd-media .pd-th{width:64px;height:64px} }
