/*
Theme Name:   Grandeurs Pantry
Theme URI:    https://grandeurspantry.co.za
Description:  Grandeurs Pantry storefront — Blocksy child theme. Design tokens and component styles from docs/01-design-tokens.md. Commerce behaviour lives in the GP Core plugin, not here, so it survives a theme change.
Author:       Unipos
Template:     blocksy
Version:      0.6.0
Requires PHP: 8.1
Text Domain:  grandeurs-pantry
*/

/* ==========================================================================
   1. TOKENS
   Sampled from client artwork. Nothing invented. See docs/01-design-tokens.md
   ========================================================================== */
:root{
  --gp-canvas:#F2F0EB;      /* single page ground, top to bottom */
  --gp-card:#FFFFFF;
  --gp-surface-2:#EAE7E0;   /* recessed wells only, never a section ground */

  --gp-ink-900:#0A0A0A;     /* brand black — masthead, hero, footer ONLY */
  --gp-ink-800:#141312;
  --gp-ink-600:#2C2822;
  --gp-ink-500:#4A463F;
  --gp-ink-300:#8A8579;
  --gp-line:#E3DFD7;
  --gp-line-dark:#26221C;

  --gp-gold-600:#8D7439;    /* gold text on light — AA safe */
  --gp-gold-500:#CA952B;    /* BRAND GOLD — primary action, accents */
  --gp-gold-400:#D4AD67;
  --gp-gold-050:#F6EEDC;

  --gp-ok:#1F7A4D;
  --gp-warn:#9A6410;
  --gp-bad:#C0182B;         /* price / savings red — reserved, never decorative */

  --gp-s1:4px;  --gp-s2:8px;  --gp-s3:12px; --gp-s4:16px; --gp-s5:24px;
  --gp-s6:32px; --gp-s7:48px; --gp-s8:64px;

  --gp-t-xs:11px; --gp-t-sm:13px; --gp-t-base:15px; --gp-t-md:17px;
  --gp-t-lg:22px; --gp-t-xl:30px; --gp-t-2xl:42px;

  --gp-serif:"Cormorant Garamond","Iowan Old Style",Georgia,serif;
  --gp-sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;

  --gp-r:4px;               /* the single radius in the system */

  /* Magnifier, inlined as a mask so it inherits the gold token and costs no
     extra request. Feather-style, 1.75 stroke, matching the icon set. */
  --gp-search-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.3-4.3'/%3E%3C/svg%3E");
}

/* ==========================================================================
   2. GLOBAL
   ========================================================================== */
body{background:var(--gp-canvas);color:var(--gp-ink-900);font-family:var(--gp-sans)}
h1,h2,h3,h4{font-family:var(--gp-serif);font-weight:600;text-wrap:balance}

/* Browser surfaces — themed, not inherited. The cheapest signal that a page
   was built rather than assembled. */
::selection{background:var(--gp-gold-500);color:var(--gp-ink-900)}
:focus-visible{outline:2px solid var(--gp-gold-500);outline-offset:2px}
body{caret-color:var(--gp-gold-600);scrollbar-color:var(--gp-ink-300) var(--gp-surface-2)}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-track{background:var(--gp-surface-2)}
::-webkit-scrollbar-thumb{background:var(--gp-ink-300)}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto!important}
}

/* Radius discipline: one value, everywhere. */
.wp-block-button__link,
.button,button,input,select,textarea,
.gp-well,.gp-card{border-radius:var(--gp-r)}

/* ==========================================================================
   3. CHROME — black is the masthead, hero and footer. Nothing else.
   Blocksy's header/footer wrappers.
   ========================================================================== */
#header .ct-header,
#header [data-row]{background:var(--gp-ink-900);color:#E8E3DA}

/* Override Blocksy's own variables inside the masthead rather than fighting
   its selectors. Blocksy paints icons and links from custom properties, so a
   plain `#header a{color:…}` rule loses to them — which is why the cart icon
   was dark on black and only appeared on hover, in the accent blue.
   Setting the variables at the header scope fixes every element at once,
   including ones not yet placed. */
#header{
  --theme-icon-color:#E8E3DA;
  --theme-icon-hover-color:#FFFFFF;
  --theme-link-initial-color:#E8E3DA;
  --theme-link-hover-color:#FFFFFF;
  --theme-text-color:#E8E3DA;
  --theme-heading-color:#FFFFFF;
  --theme-button-text-initial-color:var(--gp-ink-900);
  --theme-button-background-initial-color:var(--gp-gold-500)
}

/* The supplied logo has a black background baked into the file, a shade or
   two off the masthead, so it shows as a visible rectangle. Screen blending
   drops black to nothing against a near-black backdrop: the seam disappears
   and the gold artwork is unchanged (#CA952B screened over #0A0A0A moves by
   less than 1%).

   THIS IS A STOPGAP, NOT THE FIX. Ask the client for the logo on a
   transparent background — PNG-24 or, better, SVG. A mark with a baked
   background cannot sit on an invoice, an email header, a light surface, a
   social card or the Android splash screen, and this trick only works
   because the masthead happens to be black. */
#header [data-id="logo"] img,
#header .site-logo-container img{mix-blend-mode:screen}

/* The cart, explicitly. Its count badge is the one place gold is allowed to
   sit as a filled shape in the masthead — it is a live number, not decoration. */
#header [data-id="cart"] a,
#header [data-id="cart"] .ct-icon,
#header [data-id="cart"] svg{color:#E8E3DA;fill:currentColor}
#header [data-id="cart"] a:hover,
#header [data-id="cart"] a:hover .ct-icon,
#header [data-id="cart"] a:hover svg{color:var(--gp-gold-400)}
#header [data-id="cart"] .ct-cart-count{
  background:var(--gp-gold-500);color:var(--gp-ink-900);font-weight:700
}

/* Everything in the masthead, not just links.
   The offcanvas trigger is a <button>, not an <a>, so an `#header a` rule
   alone leaves it at Blocksy's default dark icon colour — black on black,
   invisible, and the phone is left with no navigation at all. Blocksy's icons
   paint with currentColor, so setting colour on the control is enough. */
#header a,
#header button,
#header .ct-toggle,
#header .ct-header-trigger,
#header [data-id="trigger"]{color:#E8E3DA}

#header .ct-icon,
#header .ct-toggle svg,
#header [data-id="trigger"] svg{fill:currentColor}

#header a:hover,
#header button:hover,
#header .ct-toggle:hover,
#header [data-id="trigger"]:hover{color:#fff}

/* The trigger is the only way into the menu on a phone, so give it a real
   44px tap target rather than whatever the icon happens to measure. */
#header .ct-toggle,
#header [data-id="trigger"] button{
  background:none;border:0;
  min-width:44px;min-height:44px;
  display:inline-flex;align-items:center;justify-content:center
}

.ct-header [data-id="search"] input,
.ct-header form input[type="search"]{
  background:#17150F;border:1px solid #34302A;color:#fff;
  border-radius:var(--gp-r);min-height:48px
}
.ct-header form input[type="search"]::placeholder{color:#736D62}
.ct-header form input[type="search"]:focus{border-color:var(--gp-gold-600);outline:none}

/* Persistent mobile search field.
   Blocksy's Search element is an icon that opens an overlay — there is no
   inline-input variant in the free version. A grocery shopper on a phone
   searches for "milk"; they do not browse to it. So the mobile header carries
   a real always-visible field, placed as an HTML element, matching the
   pattern Sixty60 and PnP ASAP both use.
   48px min-height is the tap target; 16px font stops iOS Safari zooming the
   viewport when the field is focused, which is the classic mobile-search bug. */
.gp-msearch{position:relative;display:block;width:100%}
.gp-msearch input[type="search"]{
  width:100%;min-height:48px;
  padding:0 var(--gp-s4) 0 var(--gp-s7);
  background:#17150F;border:1px solid #34302A;border-radius:var(--gp-r);
  color:#fff;font-family:var(--gp-sans);font-size:16px;
  -webkit-appearance:none;appearance:none
}
.gp-msearch input[type="search"]::placeholder{color:#8A8478}
.gp-msearch input[type="search"]:focus{
  border-color:var(--gp-gold-600);outline:2px solid transparent;outline-offset:2px
}
.gp-msearch::before{
  content:"";position:absolute;left:var(--gp-s4);top:50%;
  width:18px;height:18px;margin-top:-9px;pointer-events:none;
  background:var(--gp-gold-500);
  -webkit-mask:var(--gp-search-icon) center/contain no-repeat;
  mask:var(--gp-search-icon) center/contain no-repeat
}
.gp-msearch button[type="submit"]{position:absolute;left:-9999px}

/* Account link.
   Blocksy Free has no Account element, so the Button element stands in,
   pointed at /my-account/. Left alone it renders as a filled button, which is
   far too heavy sitting beside two icons. This makes it read as a text link
   matching the nav, so the masthead keeps one visual weight.
   Belt and braces on the selector: Blocksy's builder marks elements with
   data-id, but the inner class has changed across versions. */
#header [data-id="button"] a,
#header .ct-header-cta,
#header a.ct-button,
#header a.ct-button-ghost{
  background:none;border:0;box-shadow:none;
  min-height:0;padding:0 var(--gp-s1);
  font-family:var(--gp-sans);font-size:var(--gp-t-sm);font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;
  color:#E8E3DA
}
#header [data-id="button"] a:hover,
#header .ct-header-cta:hover,
#header a.ct-button:hover,
#header a.ct-button-ghost:hover{background:none;color:var(--gp-gold-400)}

/* Below 700px the masthead has room for the logo plus two controls only.
   Account moves into the drawer menu — see the Mobile menu in Appearance →
   Menus. Three controls plus the logo overflows a 375px screen. */
@media (max-width:699px){
  #header [data-id="button"]{display:none}
}

/* FOOTER
   Same trap as the masthead, and for the same reason: Blocksy paints footer
   text from its own CSS custom properties, and Blocksy's dynamic stylesheet is
   enqueued AFTER this one. A plain `color` declaration here therefore loses at
   equal specificity, and the copyright renders in Blocksy's default near-black
   on our near-black footer — invisible, which is what happened on the live
   site. Override the variables at #footer scope so every element Blocksy
   renders inside the footer inherits a legible colour, then keep the plain
   declarations as a fallback for anything that does not read the variables.

   Do not "fix" this in the Customizer instead. The Customizer writes one
   colour per element; the next footer element added starts invisible again. */
#footer,
#footer [data-row]{
  --theme-text-color:#8A8478;
  --theme-font-color:#8A8478;
  --theme-link-initial-color:#8A8478;
  --theme-link-hover-color:#C9C3B6;
  --theme-heading-color:var(--gp-gold-500);
  --theme-border-color:var(--gp-line-dark);
  background:#060605;color:#8A8478;border-top:1px solid var(--gp-line-dark)
}
body #footer,
body #footer p,
body #footer [data-id="copyright"],
body #footer [data-id="copyright"] *{color:#8A8478}
body #footer a{color:#8A8478}
body #footer a:hover{color:#C9C3B6}
#footer .widget-title,
#footer h2,#footer h3,#footer h4{
  color:var(--gp-gold-500);font-family:var(--gp-sans);font-size:var(--gp-t-xs);
  letter-spacing:.14em;text-transform:uppercase;font-weight:600
}

/* Collection strip, sits under the masthead. */
.gp-collect{background:var(--gp-ink-900);color:#B5AFA3;font-size:var(--gp-t-sm);
  border-top:1px solid var(--gp-line-dark);padding:11px 0}
.gp-collect strong{color:#fff}

/* The one gold seam: masthead/hero out into the canvas. */
.gp-seam{height:1px;background:var(--gp-gold-500);border:0;margin:0}

/* ==========================================================================
   4. BUTTONS — gold is the primary action (7.8:1 with ink text)
   ========================================================================== */
.button,
.wp-block-button__link,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.woocommerce a.button.alt,
.woocommerce button.button.alt{
  background:var(--gp-gold-500);color:var(--gp-ink-900);
  font-family:var(--gp-sans);font-size:var(--gp-t-sm);font-weight:600;
  letter-spacing:.05em;padding:14px 26px;min-height:48px;border:1px solid transparent;
  border-radius:var(--gp-r);transition:background .15s,color .15s,border-color .15s
}
.button:hover,
.wp-block-button__link:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover{background:var(--gp-gold-400);color:var(--gp-ink-900)}

.woocommerce a.button.gp-secondary,
.gp-btn-dark{background:var(--gp-ink-900);color:#fff}
.woocommerce a.button.gp-secondary:hover,
.gp-btn-dark:hover{background:var(--gp-ink-600);color:#fff}

.woocommerce .button:disabled,
.woocommerce .button.disabled{background:var(--gp-surface-2);color:var(--gp-ink-300);cursor:not-allowed}

/* Outline = the secondary action.
   WordPress core's is-style-outline paints itself with the theme's accent
   colour, which under Blocksy is a stock blue — the one colour that appears
   nowhere in this palette. It has to be set here rather than in the
   Customizer, because a block style is a front-end concern and the client
   should never have to know it exists.
   1px, not core's 2px: the system has one hairline weight. */
.wp-block-button.is-style-outline > .wp-block-button__link,
.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-text-color){
  background:transparent;
  border:1px solid var(--gp-ink-900);
  color:var(--gp-ink-900)
}
.wp-block-button.is-style-outline > .wp-block-button__link:hover{
  background:var(--gp-ink-900);border-color:var(--gp-ink-900);color:#fff
}

/* On the black hero an ink outline would disappear, so it inverts to gold.
   Gold-400 rather than gold-500: a 1px rule needs the lighter step to hold
   its edge against black. */
.gp-hero .wp-block-button.is-style-outline > .wp-block-button__link,
.gp-hero .wp-block-button.is-style-outline > .wp-block-button__link:not(.has-text-color){
  border-color:var(--gp-gold-400);color:var(--gp-gold-400)
}
.gp-hero .wp-block-button.is-style-outline > .wp-block-button__link:hover{
  background:var(--gp-gold-500);border-color:var(--gp-gold-500);color:var(--gp-ink-900)
}

/* ---------------------------------------------------------------------------
   SPECIFICITY BACKSTOP — read this before adding any rule Blocksy also sets.

   Blocksy enqueues its dynamic CSS AFTER this stylesheet. At equal specificity
   the later rule wins, so a plain `.wp-block-button__link{background:…}` loses
   to Blocksy's identical selector and the primary button reverts to its accent
   blue. The outline style survived only because `.is-style-outline > .link` is
   a two-class selector and happens to outrank it.

   That single fact explains a run of symptoms: masthead icons needing `#header`
   to hold, headings needing the Customizer, and buttons flipping back to blue.

   One extra element in the selector settles it, with no !important and no
   arms race. Anything Blocksy also styles gets the same treatment.
   ------------------------------------------------------------------------ */
/* 0.5.8 — the `.woocommerce` half of this block never matched. WooCommerce
   puts `.woocommerce` on the BODY ELEMENT, so `body .woocommerce …` looks for
   a descendant that does not exist. The `.wp-block-button__link` and
   `.wp-element-button` halves were always fine and keep their `body` prefix,
   which does its intended job there.

   Visually this changes nothing on the shop today: the add-to-cart buttons
   already render brand gold through `--theme-button-background-initial-color`
   further up. It matters for the WooCommerce `.alt` buttons — Place order,
   Proceed to checkout — which Woo styles itself and which were never covered.
   Checked against the live DOM before changing. */
body .wp-block-button__link,
body .wp-element-button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce a.button.alt,
.woocommerce button.button.alt{
  background:var(--gp-gold-500);color:var(--gp-ink-900);border-color:transparent
}
body .wp-block-button__link:hover,
body .wp-element-button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover{
  background:var(--gp-gold-400);color:var(--gp-ink-900)
}

/* Outline again, above the backstop so it is not overwritten by it. */
body .wp-block-button.is-style-outline > .wp-block-button__link{
  background:transparent;border:1px solid var(--gp-ink-900);color:var(--gp-ink-900)
}
body .wp-block-button.is-style-outline > .wp-block-button__link:hover{
  background:var(--gp-ink-900);border-color:var(--gp-ink-900);color:#fff
}
body .gp-hero .wp-block-button.is-style-outline > .wp-block-button__link{
  background:transparent;border-color:var(--gp-gold-400);color:var(--gp-gold-400)
}
body .gp-hero .wp-block-button.is-style-outline > .wp-block-button__link:hover{
  background:var(--gp-gold-500);border-color:var(--gp-gold-500);color:var(--gp-ink-900)
}

/* ==========================================================================
   4b. SHOP ARCHIVE HEADER
   The page-title band above the grid ships with a lot of vertical air. On a
   shop page that air costs the shopper a scroll before they see a single
   product, which is the opposite of what the page is for. Tighten it.

   The Customizer is the better place to change this if Blocksy's Page Title
   panel offers a spacing control — a setting beats a stylesheet override the
   client cannot see. This is the backstop for when it does not.

   KNOWN DEAD, LEFT ALONE DELIBERATELY (0.5.8). `body .woocommerce …` matches
   nothing, for the reason given at the button block above. It is NOT being
   revived in this release: the band currently renders at zero padding on the
   live category pages, so correcting the selector would ADD air to a shop page
   rather than remove it — the opposite of the intent, on a site already taking
   orders. Measure /shop/ and the category archives first, then either delete
   this block or re-point it at whatever Blocksy is actually using.
   ========================================================================== */
body .woocommerce .hero-section,
body [data-prefix="product_archive"] .hero-section,
body [data-prefix="product_cat"] .hero-section{
  padding-top:var(--gp-s5);padding-bottom:var(--gp-s5)
}
@media (min-width:1000px){
  body .woocommerce .hero-section,
  body [data-prefix="product_archive"] .hero-section,
  body [data-prefix="product_cat"] .hero-section{
    padding-top:var(--gp-s6);padding-bottom:var(--gp-s6)
  }
}

/* ==========================================================================
   4c. CATEGORY SIDEBAR
   The WooCommerce "Product categories" widget, styled as a department list.

   WHY THE WIDGET AND NOT A CUSTOM BLOCK
   It already does the two things that were asked for — nested sub-categories
   and hiding categories with nothing in them — as checkboxes the client can
   change without a developer. It also respects the hidden-category flag in
   GP Core automatically, because that filters get_terms() and the widget runs
   through it. Building our own would re-implement all three badly.

   Selectors here are WooCommerce's, not the theme's, so they are stable.
   ========================================================================== */
.widget_product_categories ul,
.wp-block-woocommerce-product-categories ul{list-style:none;margin:0;padding:0}

.widget_product_categories li,
.wp-block-woocommerce-product-categories li{margin:0}

.widget_product_categories li a,
.wp-block-woocommerce-product-categories li a{
  display:flex;justify-content:space-between;gap:var(--gp-s3);
  padding:10px 0;line-height:1.35;
  font-size:var(--gp-t-base);color:var(--gp-ink-600);
  border-bottom:1px solid var(--gp-line);
  text-decoration:none
}
.widget_product_categories li a:hover,
.wp-block-woocommerce-product-categories li a:hover{color:var(--gp-gold-600)}

/* Sub-categories: indented, quieter, hung off a rule so the hierarchy reads
   at a glance rather than needing to be worked out from indentation alone. */
.widget_product_categories .children,
.wp-block-woocommerce-product-categories .children{
  margin-left:var(--gp-s2);border-left:1px solid var(--gp-line)
}
.widget_product_categories .children a,
.wp-block-woocommerce-product-categories .children a{
  padding-left:var(--gp-s3);font-size:var(--gp-t-sm);color:var(--gp-ink-500)
}
.widget_product_categories .children .children a{padding-left:var(--gp-s5)}

/* Where you are now. */
.widget_product_categories .current-cat > a,
.wp-block-woocommerce-product-categories .current-cat > a{
  color:var(--gp-gold-600);font-weight:600
}

/* The count is reference, not a label — it must not compete with the name. */
.widget_product_categories .count,
.wp-block-woocommerce-product-categories .count{
  flex:none;font-size:var(--gp-t-xs);color:var(--gp-ink-300);font-variant-numeric:tabular-nums
}

/* Sidebar section label.
   The block-based Product Categories List has no title of its own — the title
   is a separate Heading block sitting next to it, so it cannot be styled as a
   descendant of the widget. Hence an explicit class, applied in the block's
   Advanced → Additional CSS class(es) field. Without it the heading renders as
   a 30px serif h2, which shouts over the list it is labelling. */
.gp-side-title,
.widget_product_categories > h2,
.widget_product_categories .widget-title,
.wp-block-woocommerce-product-categories > h2{
  font-family:var(--gp-sans);font-size:var(--gp-t-xs);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--gp-ink-500);
  margin:0 0 var(--gp-s2);line-height:1.4
}

/* A dropdown variant, if the client ever switches the widget to one. */
.widget_product_categories select{
  width:100%;min-height:44px;padding:0 var(--gp-s3);
  border:1px solid var(--gp-line);background:var(--gp-card);font-size:16px
}

/* MOBILE: the sidebar stacks BELOW the grid, which puts the category list
   under twenty-four products where nobody will ever see it. Hide it there and
   let the masthead menu carry navigation, which is what it is for. Revisit if
   the department count grows past what the menu can hold. */
@media (max-width:999px){
  .ct-sidebar .widget_product_categories,
  .ct-sidebar .wp-block-woocommerce-product-categories{display:none}
}

/* ==========================================================================
   5. PRODUCT GRID — white cards on the canvas, hairline border, no shadow
   ========================================================================== */
.woocommerce ul.products{
  display:grid;grid-template-columns:repeat(2,1fr);gap:var(--gp-s3);margin:0;padding:0
}
.woocommerce ul.products::before,
.woocommerce ul.products::after{content:none}
.woocommerce ul.products li.product{
  width:auto!important;margin:0!important;float:none!important;clear:none!important;
  background:var(--gp-card);border:1px solid var(--gp-line);border-radius:var(--gp-r);
  padding:var(--gp-s3) var(--gp-s3) var(--gp-s4);
  display:flex;flex-direction:column;gap:var(--gp-s3);
  transition:border-color .15s
}
.woocommerce ul.products li.product:hover{border-color:var(--gp-gold-400)}

@media (min-width:560px){
  .woocommerce ul.products{grid-template-columns:repeat(3,1fr);gap:var(--gp-s4)}
  .woocommerce ul.products li.product{padding:var(--gp-s4) var(--gp-s4) var(--gp-s5)}
}
/* 1280, not 1000: with the category sidebar taking a column, four product
   cards at 1000px leaves each one too narrow to read the name without
   wrapping to three lines. Three cards beside the sidebar, four only once
   there is genuinely room for both. */
@media (min-width:1280px){
  .woocommerce ul.products{grid-template-columns:repeat(4,1fr)}
}

/* Image well */
.gp-well{position:relative;aspect-ratio:1;background:var(--gp-canvas);
  display:grid;place-items:center;overflow:hidden}
.gp-well img{width:100%;height:100%;object-fit:cover;display:block;margin:0}

/* The placeholder well: a mark, not a photograph. It must not be stretched to
   fill the cell the way a product shot is, so it overrides the cover rule
   above — hence the doubled class, which beats a single one on specificity
   without reaching for !important. */
.gp-well.gp-well--placeholder{background:var(--gp-surface-2)}
/* !important here for the same reason as the packshot rule below: that rule
   has to force `width:100%` past Blocksy's inline sizing, and it would
   otherwise stretch this mark to fill the cell. The mark must stay small. */
.gp-well.gp-well--placeholder img{
  width:50%!important;height:auto;max-height:50%;object-fit:contain;
  opacity:.5;margin:auto;padding:0;border:0
}
.woocommerce ul.products li.product a img{margin:0;box-shadow:none}

/* PACKSHOTS ARE NOT LIFESTYLE PHOTOGRAPHY — DO NOT CROP THEM.
   The theme fits product images to a portrait cell with object-fit:cover,
   which crops to fill. That is right for a photograph of a counter and wrong
   for a product on white: a square jar in a 3:4 box loses its top and bottom,
   taking the lid and the brand name with them. A shopper scanning a grid
   identifies the product by the pack, so cropping the pack costs sales.

   `contain` letterboxes instead, which leaves white space around a wide or
   tall pack. That is the correct trade: whitespace reads as deliberate, a
   sliced-off logo reads as broken.

   ---------------------------------------------------------------------------
   0.5.8 — THIS RULE NEVER APPLIED. Two separate faults, both now fixed.

   1. The `body ` prefix was wrong, not merely redundant. WooCommerce puts
      `.woocommerce` on the BODY ELEMENT ITSELF, not on a wrapper div, so
      `body .woocommerce …` asks for a `.woocommerce` descendant of body and
      matches nothing on this site. Verified in the live DOM, where body
      carries `…theme-blocksy woocommerce woocommerce-page…`. Dropping the
      prefix is enough: `.woocommerce ul.products li.product img` is four
      classes deep and comfortably outranks Blocksy's `.ct-media-container img`.

   2. Blocksy writes `style="aspect-ratio: 3/4"` INLINE on every product
      thumbnail, from its Customizer image-ratio setting. No selector beats an
      inline style, which is the one place `!important` is the correct tool
      rather than an arms race. The products are square 500x500 exports from
      the POS, so a 3:4 box was cropping every one of them.

   The better home for (2) is Blocksy ▸ Customizer ▸ WooCommerce ▸ Product
   Archives ▸ card image ratio, set to 1:1 — a setting the client can see beats
   a stylesheet override they cannot. This stays as the backstop, and so that
   the grid is correct on a fresh install before anyone touches the Customizer.

   `--theme-object-fit` is Blocksy's own variable, read by its media rules.
   Setting it is the framework-sanctioned override and costs no specificity.

   If genuine lifestyle photography is ever used for products, revisit this —
   those images DO want cover. Set it per category rather than globally. */
.woocommerce ul.products li.product figure,
.woocommerce ul.products li.product .ct-media-container{
  display:block;width:100%;margin:0;overflow:hidden;
  border:1px solid var(--gp-line);border-radius:var(--gp-r);background:#fff
}
.woocommerce ul.products li.product .ct-media-container{--theme-object-fit:contain}

/* When GP Core's own well IS drawn (gp_core_loop_thumbnail_active), the markup
   nests as .gp-well > figure > a.ct-media-container, so the rule above would
   put a second border inside the well's own rounded box. The well is the
   container in that case; the figure is just a wrapper. */
.gp-well figure,
.gp-well .ct-media-container{border:0;border-radius:0;background:transparent}

.woocommerce ul.products li.product img,
.woocommerce ul.products li.product .ct-media-container img,
.wc-block-grid__product img{
  aspect-ratio:1/1!important;   /* beats Blocksy's inline 3/4 — see above */
  width:100%!important;
  height:auto;
  object-fit:contain;
  background:#fff;
  padding:6px
}

/* One badge maximum, top-left of the well — or of the card itself when the
   theme renders its own thumbnail and there is no well. .gp-tag is absolutely
   positioned, so it needs a positioned ancestor either way; without this it
   would escape to the nearest one, which is the page. */
.woocommerce ul.products li.product,
.wc-block-grid__product{position:relative}
.gp-tag{position:absolute;top:7px;left:7px;z-index:2;
  font-family:var(--gp-sans);font-size:10px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;padding:4px 8px;color:#fff;border-radius:2px}
.gp-tag--sale{background:var(--gp-bad)}
.gp-tag--new{background:var(--gp-ink-900);color:var(--gp-gold-400)}

/* The theme prints its own sale flash as well as ours, so a discounted product
   wore "SPECIAL" and "SALE" stacked on top of each other. Ours carries the
   brand styling and the wording we chose, so the theme's goes.

   `.onsale` is WooCommerce's own class, which themes conventionally reuse. If
   the duplicate badge survives this, the theme is using a class of its own and
   I need to see the card markup to target it. SOLD OUT is deliberately left
   alone — that one is information the shopper needs. */
.woocommerce ul.products li.product span.onsale,
.woocommerce ul.products li.product .onsale{display:none}

/* Empty state for /specials/ when nothing is on sale. */
.gp-empty{
  padding:var(--gp-s7) 0;text-align:center;color:var(--gp-ink-500);
  font-size:var(--gp-t-md)
}
.gp-empty .gp-more{font-size:var(--gp-t-base)}

/* Cell typography */
.gp-brand{display:block;font-size:var(--gp-t-xs);letter-spacing:.11em;
  text-transform:uppercase;color:var(--gp-ink-300)}
.woocommerce ul.products li.product .woocommerce-loop-product__title{
  font-family:var(--gp-sans);font-size:var(--gp-t-base);font-weight:600;
  line-height:1.3;color:var(--gp-ink-900);padding:0;margin:0
}
.woocommerce ul.products li.product:hover .woocommerce-loop-product__title{
  text-decoration:underline;text-decoration-color:var(--gp-gold-500);text-underline-offset:3px
}
.gp-size{display:block;font-size:var(--gp-t-sm);color:var(--gp-ink-500)}

.woocommerce ul.products li.product .price{
  font-family:var(--gp-sans);font-size:var(--gp-t-md);font-weight:700;
  color:var(--gp-ink-900);margin:auto 0 0;font-variant-numeric:tabular-nums;
  display:flex;align-items:baseline;gap:8px;padding-top:var(--gp-s2)
}
.woocommerce ul.products li.product .price ins{
  text-decoration:none;color:var(--gp-bad);font-weight:700;background:none
}
.woocommerce ul.products li.product .price del{
  font-size:var(--gp-t-sm);color:var(--gp-ink-300);opacity:1;font-weight:400
}

/* Stock state — text, never a number */
.gp-stock{display:block;font-size:var(--gp-t-xs);font-weight:600;letter-spacing:.04em}
.gp-stock--in{color:var(--gp-ok)}
.gp-stock--low{color:var(--gp-warn)}
.gp-stock--out{color:var(--gp-bad)}

/* Add to basket fills the cell width */
.woocommerce ul.products li.product .button{
  width:100%;text-align:center;padding:11px;min-height:42px;
  font-size:var(--gp-t-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase
}

/* ==========================================================================
   6. SINGLE PRODUCT
   ========================================================================== */
.woocommerce div.product .product_title{
  font-size:var(--gp-t-xl);line-height:1.08;margin-top:6px
}
@media (min-width:700px){.woocommerce div.product .product_title{font-size:var(--gp-t-2xl)}}

.gp-brand--single{margin-bottom:2px}
.gp-size--single{color:var(--gp-ink-500);margin:8px 0 0}

.woocommerce div.product p.price,
.woocommerce div.product span.price{
  font-family:var(--gp-sans);font-size:var(--gp-t-xl);font-weight:700;
  color:var(--gp-ink-900);font-variant-numeric:tabular-nums;
  display:flex;align-items:baseline;gap:12px;margin-top:var(--gp-s5)
}
.woocommerce div.product p.price ins{text-decoration:none;color:var(--gp-bad);background:none}
.woocommerce div.product p.price del{font-size:var(--gp-t-md);color:var(--gp-ink-300);opacity:1}

.woocommerce div.product .woocommerce-product-gallery{border:1px solid var(--gp-line);
  border-radius:var(--gp-r);overflow:hidden;background:var(--gp-canvas)}

.gp-facts{display:grid;grid-template-columns:auto 1fr;gap:9px var(--gp-s5);margin:0}
.gp-facts dt{color:var(--gp-ink-300);font-size:var(--gp-t-sm)}
.gp-facts dd{margin:0;color:var(--gp-ink-900);font-size:var(--gp-t-sm)}

/* Quantity stepper */
.woocommerce .quantity input.qty{
  min-height:48px;border:1px solid var(--gp-line);background:var(--gp-card);
  border-radius:var(--gp-r);font-weight:600;font-variant-numeric:tabular-nums
}

/* ==========================================================================
   7. CART & CHECKOUT
   ========================================================================== */
.woocommerce-cart table.cart{
  background:var(--gp-card);border:1px solid var(--gp-line);border-radius:var(--gp-r)
}

/* Why delivery is not in the list (GP_Delivery::render_minimum_nudge).
   Sits directly above the shipping choices, so it answers the question at the
   moment it is asked. Deliberately informational rather than an alert — the
   basket is not wrong, it is simply small. */
.gp-min-note td{padding:0 0 var(--gp-s3)!important}
.gp-min-note p{
  margin:0;padding:10px 12px;
  background:var(--gp-surface-2);border-left:3px solid var(--gp-gold-500);
  border-radius:0 var(--gp-r) var(--gp-r) 0;
  font-size:var(--gp-t-sm);line-height:1.5;color:var(--gp-ink-500)
}
.gp-min-note strong{color:var(--gp-ink-900)}
.woocommerce table.shop_table td,
.woocommerce table.shop_table th{border-color:var(--gp-line)}

/* ORDER SUMMARY — a box inside a box is what made this look untidy.
   The review table was given its own card treatment, but it sits INSIDE
   #order_review, which is already a card. Two borders, two backgrounds, nested.
   Strip the table back to rows and let the panel be the card. */
.woocommerce-checkout .woocommerce-checkout-review-order-table{
  background:transparent;border:0;border-radius:0;
  width:100%;margin:0;border-collapse:collapse
}
.woocommerce-checkout .woocommerce-checkout-review-order-table td,
.woocommerce-checkout .woocommerce-checkout-review-order-table th{
  border-left:0;border-right:0;padding:var(--gp-s3) 0
}

/* Column headings are a label, not a title. */
.woocommerce-checkout .woocommerce-checkout-review-order-table thead th{
  font-size:var(--gp-t-xs);letter-spacing:.1em;text-transform:uppercase;
  color:var(--gp-ink-500);font-weight:600;
  padding:0 0 var(--gp-s2);border-bottom:1px solid var(--gp-line)
}
.woocommerce-checkout .woocommerce-checkout-review-order-table thead th:last-child{
  text-align:right
}

/* Line items. POS product names are long and in capitals, so the name needs
   room to wrap and the price needs to stay on one line beside it. */
.woocommerce-checkout .cart_item td{border-bottom:1px solid var(--gp-line)}
.woocommerce-checkout .cart_item .product-name{
  color:var(--gp-ink-900);font-size:var(--gp-t-sm);line-height:1.45;
  padding-right:var(--gp-s4);width:72%
}
.woocommerce-checkout .cart_item .product-quantity{
  display:inline;color:var(--gp-ink-500);font-weight:600;white-space:nowrap
}
.woocommerce-checkout .cart_item .product-total{
  text-align:right;white-space:nowrap;vertical-align:top;
  font-variant-numeric:tabular-nums;color:var(--gp-ink-900)
}

/* Totals. Subtotal and shipping are reference; the total is the number the
   customer is agreeing to pay, so only it carries weight. */
.woocommerce-checkout .woocommerce-checkout-review-order-table tfoot th{
  font-weight:400;color:var(--gp-ink-500);font-size:var(--gp-t-sm);
  text-align:left;border-bottom:0
}
.woocommerce-checkout .woocommerce-checkout-review-order-table tfoot td{
  text-align:right;font-variant-numeric:tabular-nums;border-bottom:0
}
.woocommerce-checkout .woocommerce-checkout-review-order-table tfoot .order-total th,
.woocommerce-checkout .woocommerce-checkout-review-order-table tfoot .order-total td{
  border-top:1px solid var(--gp-line);padding-top:var(--gp-s4);
  font-size:var(--gp-t-md);font-weight:700;color:var(--gp-ink-900)
}

/* "Enter your address to view shipping options" — guidance, not a heading. */
.woocommerce-checkout .woocommerce-shipping-destination,
.woocommerce-checkout td[data-title="Shipping"] p,
.woocommerce-checkout .shipping td p{
  font-size:var(--gp-t-sm);color:var(--gp-ink-500);font-weight:400;margin:0
}

/* Payment method rows: a real tap target, and the selected one legible. */
.woocommerce-checkout #payment ul.payment_methods li{
  list-style:none;margin:0;padding:0
}
.woocommerce-checkout #payment ul.payment_methods li label{
  display:inline-flex;align-items:center;gap:var(--gp-s2);
  min-height:44px;font-weight:600;color:var(--gp-ink-900);
  font-size:var(--gp-t-base);letter-spacing:0;text-transform:none
}
.woocommerce-checkout #payment ul.payment_methods .payment_box{
  background:var(--gp-surface-2);border-radius:var(--gp-r);
  padding:var(--gp-s3);margin:0 0 var(--gp-s3);
  font-size:var(--gp-t-sm);color:var(--gp-ink-500)
}
.woocommerce-checkout #payment ul.payment_methods .payment_box::before{display:none}

.woocommerce-checkout .woocommerce-billing-fields,
.woocommerce-checkout #order_review,
.woocommerce .cart_totals{
  background:var(--gp-card);border:1px solid var(--gp-line);
  border-radius:var(--gp-r);padding:var(--gp-s5)
}
@media (min-width:700px){
  .woocommerce-checkout .woocommerce-billing-fields,
  .woocommerce-checkout #order_review,
  .woocommerce .cart_totals{padding:var(--gp-s6)}
}

.woocommerce form .form-row label{
  font-size:var(--gp-t-xs);letter-spacing:.1em;text-transform:uppercase;
  color:var(--gp-ink-500);font-weight:600
}
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row select,
.woocommerce form .form-row textarea{
  padding:13px 14px;min-height:48px;border:1px solid var(--gp-line);
  background:var(--gp-card);border-radius:var(--gp-r);
  font-size:var(--gp-t-base);color:var(--gp-ink-900)
}
.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row select:focus{border-color:var(--gp-gold-600);outline:none}

.woocommerce-checkout #payment{background:transparent;border-radius:0}
.woocommerce-checkout #payment ul.payment_methods{
  background:var(--gp-card);border:1px solid var(--gp-line);
  border-radius:var(--gp-r);padding:var(--gp-s4)
}
.woocommerce-checkout #payment div.form-row{padding:var(--gp-s4) 0 0}

/* Free collection reads as a benefit, not a blank */
.woocommerce-shipping-totals .woocommerce-Price-amount,
.gp-free{color:var(--gp-ok);font-weight:600}

/* ==========================================================================
   8. NOTICES — square, branded, no emoji
   ========================================================================== */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error{
  border-radius:var(--gp-r);border-top:none;border-left:3px solid var(--gp-gold-500);
  background:var(--gp-gold-050);color:#5A4818;font-size:var(--gp-t-base)
}
.woocommerce-error{border-left-color:var(--gp-bad);background:#FCF2F3;color:#7A1520}
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before{color:inherit}

/* ==========================================================================
   9. HOME PATTERNS (registered in inc/patterns.php)
   ========================================================================== */
.gp-hstrip{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;background:var(--gp-ink-900)}
.gp-hstrip img{width:100%;height:100%;object-fit:cover;aspect-ratio:1;display:block}
@media (min-width:560px){.gp-hstrip img{aspect-ratio:3/2;max-height:210px}}
@media (min-width:1100px){.gp-hstrip img{aspect-ratio:16/9;max-height:200px}}

.gp-hero{background:var(--gp-ink-900);color:#fff;text-align:center}
.gp-hero .gp-inner{max-width:1040px;margin:0 auto;padding:var(--gp-s7) var(--gp-s5)}
.gp-hero .gp-emblem{width:74px;margin:0 auto var(--gp-s3)}
.gp-hero h1{font-size:var(--gp-t-xl);line-height:1.04;margin:var(--gp-s5) 0 0;color:#fff}
.gp-hero h1 b{color:var(--gp-gold-400);font-weight:600}
.gp-hero p{color:#C2BCAF;max-width:52ch;margin:var(--gp-s4) auto 0;font-size:var(--gp-t-base);line-height:1.6}
.gp-hero .gp-cta{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:var(--gp-s6)}
.gp-hero .gp-meta{margin-top:var(--gp-s7);padding-top:var(--gp-s5);
  border-top:1px solid var(--gp-line-dark);display:grid;grid-template-columns:1fr;
  gap:var(--gp-s4);font-size:var(--gp-t-sm);color:#8F897C}
.gp-hero .gp-meta b{display:block;color:#E8E3DA;font-weight:600;margin-bottom:4px}

/* Centred, capped and top-aligned.
   Centring is right here because the whole hero is centred — the earlier
   raggedness was not the alignment, it was one cell running three rules of
   trading hours together into a single wrapped paragraph. Each rule now gets
   its own line in the markup, so the cells read as short stacks rather than
   prose, and a capped measure keeps them from spanning the full column. */
.gp-hero .gp-meta{align-items:start}
.gp-hero .gp-meta > div{max-width:34ch;margin-inline:auto;line-height:1.65}
.gp-lockmark{font-family:var(--gp-serif);letter-spacing:.2em;font-size:19px;line-height:1.1}
.gp-lockmark em{display:block;font-style:normal;font-size:9px;letter-spacing:.42em;
  color:var(--gp-gold-500);margin-top:6px}
.gp-desc{display:inline-flex;align-items:center;gap:10px;margin-top:6px;
  font-size:8.5px;letter-spacing:.34em;text-transform:uppercase;color:#8F897C}
.gp-desc i{display:block;width:26px;height:1px;background:var(--gp-gold-600)}

@media (min-width:560px){
  .gp-hero .gp-emblem{width:96px}
  .gp-lockmark{font-size:26px}
  .gp-lockmark em{font-size:10.5px}
  .gp-desc{font-size:10px}
  .gp-hero h1{font-size:48px}
  .gp-hero p{font-size:19px}
  .gp-hero .gp-meta{grid-template-columns:repeat(3,1fr);font-size:var(--gp-t-base)}
  .gp-hero .gp-cta .button{padding:16px 30px;font-size:14.5px;min-height:52px}
}
@media (min-width:1100px){
  .gp-hero .gp-inner{padding:var(--gp-s7) var(--gp-s6)}
  .gp-hero .gp-emblem{width:112px}
  .gp-lockmark{font-size:32px}
  .gp-hero h1{font-size:62px}
  .gp-hero p{font-size:21px;max-width:48ch}
}

/* Section rhythm.
   Each pattern inserts as its own block group with no margin of its own, so
   without this the three sections butt together and read as one crowded
   block — heading, cards, heading, cards, with nothing telling the eye where
   one ends. The space between sections is what makes them sections. */
.gp-shead{margin-top:var(--gp-s7)}
.gp-cards{margin-bottom:var(--gp-s7)}
@media (min-width:700px){
  .gp-shead{margin-top:var(--gp-s8)}
  .gp-cards{margin-bottom:var(--gp-s8)}
}

/* Section heading with the rule beneath, on one measure.

   Grid, not flex, because the heading has to be centred on the SECTION while a
   right-hand link ("Shop all") keeps its own place. Flex with space-between
   centres nothing — it pushes the two children apart, so the heading lands
   wherever the link's width leaves it, and a longer link would shift it again.
   Three columns — 1fr | auto | 1fr — pin the heading to the true centre and
   leave the link in the right-hand track. A section with no link (Also in
   store) keeps the same centre, because the empty third column is still 1fr. */
.gp-shead{display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;
  gap:var(--gp-s5);padding-bottom:var(--gp-s3);
  border-bottom:1px solid var(--gp-line);margin-bottom:var(--gp-s4)}
.gp-shead h2{grid-column:2;text-align:center;font-size:var(--gp-t-xl);line-height:1.1;margin:0}
.gp-shead .gp-more{grid-column:3;justify-self:end}
@media (min-width:700px){.gp-shead h2{font-size:var(--gp-t-2xl)}}
.gp-shead .gp-more{font-size:var(--gp-t-sm);font-weight:600;color:var(--gp-gold-600);
  white-space:nowrap;border-bottom:1px solid transparent;padding-bottom:2px}
.gp-shead .gp-more:hover{border-bottom-color:var(--gp-gold-500)}

/* Below 560px the three tracks cannot hold a 30px serif heading and a link
   without squeezing the heading onto two lines. Stack instead: heading
   centred, link centred under it. Still centred, still one rule. */
@media (max-width:559px){
  .gp-shead{grid-template-columns:1fr;gap:var(--gp-s2);justify-items:center}
  .gp-shead h2,
  .gp-shead .gp-more{grid-column:1;justify-self:center}
}

/* Department and in-store cells */
.gp-cards{display:grid;gap:var(--gp-s4);grid-template-columns:1fr}
@media (min-width:700px){.gp-cards--2{grid-template-columns:repeat(2,1fr)}}
@media (min-width:560px){.gp-cards--5{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1100px){.gp-cards--5{grid-template-columns:repeat(5,1fr)}}
.gp-card{background:var(--gp-card);border:1px solid var(--gp-line);
  border-radius:var(--gp-r);overflow:hidden;display:flex;flex-direction:column}
.gp-card:hover{border-color:var(--gp-gold-400)}
.gp-card img{width:100%;aspect-ratio:16/10;object-fit:cover;display:block}
.gp-card .gp-body{padding:var(--gp-s4);display:flex;flex-direction:column;gap:5px}
.gp-card .gp-dn{font-size:var(--gp-t-xs);letter-spacing:.12em;text-transform:uppercase;
  color:var(--gp-gold-600);font-weight:600}
.gp-card .gp-bn{font-family:var(--gp-serif);font-size:var(--gp-t-lg);line-height:1.15}
.gp-card .gp-dc{font-size:var(--gp-t-sm);color:var(--gp-ink-500)}

/* The two department tiles carry no photography, and they sit directly above
   five cards that do. Left at the same proportions they read as cards whose
   images failed to load rather than as a deliberate choice.
   Grocery has no counter photograph — one tile with a picture beside one
   without would be worse — so these are built as navigation tiles instead:
   taller, the department name at display size, and an explicit affordance. */
.gp-cards--2 .gp-card{min-height:170px;justify-content:center}
.gp-cards--2 .gp-card .gp-body{padding:var(--gp-s5);gap:var(--gp-s2)}
.gp-cards--2 .gp-card .gp-bn{font-size:var(--gp-t-xl)}
.gp-cards--2 .gp-card .gp-dc{max-width:44ch}
.gp-cards--2 .gp-card .gp-body::after{
  content:"\2192";
  margin-top:var(--gp-s2);
  font-size:var(--gp-t-md);line-height:1;
  color:var(--gp-gold-600);
  transition:transform .15s
}
.gp-cards--2 .gp-card:hover .gp-body::after{transform:translateX(4px)}

/* -------------------------------------------------------------------------
 * Single-variation products
 *
 * The POS exports most lines as variable products because some genuinely
 * have several pack sizes. Where there is only one, GP Core preselects it
 * and marks the product `.gp-single-variation`; all that is left is to stop
 * showing a dropdown whose only purpose is to be opened and closed again.
 *
 * The <select> stays in the DOM, preselected, so the form still posts the
 * right variation and WooCommerce's variation script still resolves the
 * price and enables the button. Only the row is hidden.
 *
 * `.reset_variations` goes too — there is nothing to reset to.
 * ---------------------------------------------------------------------- */

body .gp-single-variation .variations,
body .gp-single-variation .reset_variations {
	display: none;
}

/* Without the table above it the button sits hard against the price. */
body .gp-single-variation .woocommerce-variation-add-to-cart {
	margin-top: var(--wp--preset--spacing--40, 16px);
}

/* Blocksy renders the stock line inside the variation wrapper; with a single
   fixed option it is the same line already shown above, so it reads twice. */
body .gp-single-variation .woocommerce-variation-availability {
	display: none;
}

/* -------------------------------------------------------------------------
 * Department navigation — [gp_department_nav]
 *
 * Built on <details>/<summary>, so the open/closed state, keyboard handling
 * and screen-reader semantics come from the browser. The only thing CSS does
 * here is remove the default marker and draw our own chevron.
 * ---------------------------------------------------------------------- */

.gp-depts {
	font-size: 0.875rem;
	line-height: 1.35;
}

.gp-depts-h {
	margin: 0 0 10px;
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--gold-600, #8D7439);
}

.gp-depts-l,
.gp-dept-k {
	margin: 0;
	padding: 0;
	list-style: none;
}

.gp-dept {
	border-bottom: 1px solid var(--wp--preset--color--line, #E3DFD7);
}

/* Shared row: name on the left, count hard right. The widget this replaces
   broke the count onto its own line, which is what made the list so tall. */
.gp-dept-s,
.gp-dept > a,
.gp-dept-k a {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 10px 2px;
	color: var(--wp--preset--color--ink-500, #4A463F);
	text-decoration: none;
}

.gp-dn-n,
.gp-dept > a,
.gp-dept-k a {
	min-width: 0;
}

.gp-dn-n {
	flex: 1 1 auto;
}

.gp-dn-c {
	flex: 0 0 auto;
	margin-left: auto;
	font-size: 0.6875rem;
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--ink-300, #8A8579);
}

/* The disclosure row. */
.gp-dept-s {
	cursor: pointer;
	font-weight: 600;
	color: var(--wp--preset--color--ink-900, #0A0A0A);
	list-style: none;
}

.gp-dept-s::-webkit-details-marker { display: none; }
.gp-dept-s::marker { content: ""; }

/* Our own chevron, rotated by the open state. */
.gp-dept-s::before {
	content: "";
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	margin-right: 2px;
	border-right: 1.5px solid var(--wp--preset--color--gold-600, #8D7439);
	border-bottom: 1.5px solid var(--wp--preset--color--gold-600, #8D7439);
	transform: rotate(-45deg);
	transition: transform 0.18s ease;
}

.gp-dept details[open] > .gp-dept-s::before {
	transform: rotate(45deg);
}

.gp-dept-s:hover,
.gp-dept > a:hover,
.gp-dept-k a:hover {
	color: var(--wp--preset--color--gold-600, #8D7439);
}

/* Children. */
.gp-dept-k {
	padding: 0 0 8px 17px;
	border-left: 1px solid var(--wp--preset--color--line, #E3DFD7);
	margin-left: 5px;
}

.gp-dept-k a {
	padding: 7px 2px;
	font-size: 0.8125rem;
}

.gp-dept-k em {
	font-style: normal;
	font-weight: 600;
	color: var(--wp--preset--color--gold-600, #8D7439);
}

/* Where the customer is now. */
.gp-dept-k a.is-here,
.gp-dept-s.is-here,
.gp-dept--leaf.is-here > a {
	color: var(--wp--preset--color--ink-900, #0A0A0A);
	font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
	.gp-dept-s::before { transition: none; }
}

/* A long catalogue should not push the product grid down the page. */
@media (min-width: 1000px) {
	.gp-depts-l {
		max-height: 70vh;
		overflow-y: auto;
		overscroll-behavior: contain;
	}
}

/* The permanent install control — [gp_install_app].
   Hidden until the browser says the site is installable; pwa.js unhides it. */
.gp-install-link {
	appearance: none;
	border: 1px solid currentColor;
	border-radius: 8px;
	background: transparent;
	color: inherit;
	font: inherit;
	font-size: 0.8125rem;
	font-weight: 600;
	padding: 8px 14px;
	cursor: pointer;
}

.gp-install-link:hover {
	color: var(--wp--preset--color--gold-500, #CA952B);
}

.gp-install-link[hidden] { display: none; }


/* ==========================================================================
   10. NATIVE APP — safe areas under the Android system bars
   Applies only under .gp-app, which inc/app.php adds server-side when the
   Capacitor user agent is recognised. A browser visitor never matches any of
   this, so nothing here can regress the website.
   ========================================================================== */

/*
 * WHY THIS SECTION EXISTS
 *
 * The app targets SDK 36. From Android 15 the system draws the status bar and
 * the gesture navigation bar OVER the app's window and there is no opt-out, so
 * the WebView now gets the whole screen — including the strips the clock and
 * the gesture pill sit in. Without the padding below, the masthead logo starts
 * underneath the clock and the last row of the footer sits under the pill.
 *
 * WHERE THE NUMBERS COME FROM, AND WHY THERE ARE TWO SOURCES
 *
 * Capacitor 8's SystemBars plugin handles insets one of two ways, decided per
 * device at runtime:
 *
 *   - WebView 140 or newer AND the page declares viewport-fit=cover (Blocksy
 *     does, on every page) — the insets are passed through to the page, so
 *     env(safe-area-inset-*) is live, AND the plugin also writes
 *     --safe-area-inset-* onto the documentElement.
 *   - Anything older — the plugin pads the native decor view instead, so the
 *     WebView is already inset, and it writes --safe-area-inset-*: 0px.
 *
 * Reading --safe-area-inset-* FIRST and falling back to env() is therefore
 * correct in both cases and in both directions: on the second path the
 * variable is 0px and this section adds nothing, because the padding has
 * already happened natively and adding ours would double it. The env()
 * fallback covers the gap before the plugin's first injection lands, and iOS
 * later, where there is no injection at all.
 *
 * Consequence worth knowing: on a device where the insets are zero, every rule
 * below is a no-op. That is the intended behaviour, not a silent failure.
 */
.gp-app {
	--gp-safe-top: var( --safe-area-inset-top, env( safe-area-inset-top, 0px ) );
	--gp-safe-bottom: var( --safe-area-inset-bottom, env( safe-area-inset-bottom, 0px ) );
	--gp-safe-left: var( --safe-area-inset-left, env( safe-area-inset-left, 0px ) );
	--gp-safe-right: var( --safe-area-inset-right, env( safe-area-inset-right, 0px ) );
}

/*
 * The top strip, on <body>.
 *
 * Padding goes here rather than on #main-container or #header because the
 * padding shows the padded element's OWN background, and both of those are
 * transparent — the black masthead colour is on a row deeper inside Blocksy's
 * header. Padding either would have put a cream band above a black masthead.
 * body is the element that can be made black without touching Blocksy's
 * structure, so the strip reads as the top of the masthead, which is also what
 * the PWA theme-color already claims.
 *
 * The left/right insets matter only in landscape on a notched device, where
 * they are the difference between a readable first column and one behind the
 * cutout.
 *
 * There is no sticky header on this site (verified in the live document: the
 * only fixed elements are Blocksy's two panels, handled below), so content
 * scrolling under the status bar after the first screen is the normal
 * edge-to-edge behaviour and is left alone.
 */
.gp-app {
	padding-top: var( --gp-safe-top );
	padding-left: var( --gp-safe-left );
	padding-right: var( --gp-safe-right );
	background-color: var( --gp-ink-900 );
}

/* #main-container is transparent by default and would now show the black
   above through the whole page. Give it the canvas it is drawn against. */
.gp-app #main-container {
	background-color: var( --gp-canvas );
}

/* The bottom strip. #footer carries its own near-black background, so padding
   it extends that colour under the gesture pill — no extra element needed. */
.gp-app #footer {
	padding-bottom: var( --gp-safe-bottom );
}

/*
 * Blocksy's two full-screen overlays: the mobile menu (#offcanvas) and the
 * search panel (#search-modal). Both are position:fixed, so they are laid out
 * against the viewport and ignore the body padding above entirely — without
 * their own insets the close button sits under the clock and the last menu
 * item under the gesture pill. These are the two places in the app where
 * missing insets would make something genuinely unusable rather than merely
 * untidy.
 */
.gp-app .ct-panel-inner,
.gp-app .ct-panel-content {
	padding-top: var( --gp-safe-top );
	padding-bottom: var( --gp-safe-bottom );
}

/* The search panel's close button lives in its own row above the content. */
.gp-app #search-modal .ct-panel-actions {
	padding-top: var( --gp-safe-top );
}

/*
 * The install prompt has no business appearing inside the installed app, and
 * pwa.php already stops it being offered. This is the backstop for anything
 * that reaches the DOM another way — a cached page from before the app
 * shipped, or a future WebView that starts firing beforeinstallprompt.
 */
.gp-app .gp-install,
.gp-app .gp-install-link {
	display: none !important;
}
