/* ============================================================
   URTICA HERBAL — Snipcart v3 theme skin.
   Loaded by the shop and the 16 product pages, after urtica.css.

   WHY THIS FILE EXISTS: Snipcart ships its own ~100 KB default
   stylesheet (Open Sans / Montserrat, #194cb3 blue buttons, grey
   #f1f2f4 canvas, 4px radii). None of that belongs to this site,
   so the basket and the checkout read as a different company's
   product bolted onto the end of the funnel. This file restates
   Snipcart's surface in Urtica's tokens.

   TWO MECHANISMS, AND WHY BOTH:

   1. Custom properties on `#snipcart`. Snipcart's CSS reads every
      colour as `var(--name, <fallback>)` and never defines the
      variable itself, so declaring it here wins no matter which
      stylesheet loaded first. The names below are not invented —
      they are the exact set harvested from
      cdn.snipcart.com/themes/v3.9.0/default/snipcart.css. The page
      snippet pins that version; check these names again before
      moving it, because a renamed variable fails silently back to
      blue rather than erroring.

   2. Direct rules, every one prefixed `#snipcart`. Fonts, radii and
      sizes are hard-coded in Snipcart's CSS, not tokenised. Snipcart
      injects its stylesheet into <head> when the cart first loads —
      i.e. AFTER this file — so a plain `.snipcart-base-button {}`
      here would lose on source order. The `#snipcart` prefix buys ID
      specificity, which no class-only selector can beat regardless
      of order. Keep the prefix on every rule; dropping it is the
      failure mode.

   SCOPE: verified against the live site 18 Aug 2026 — the whole cart
   and checkout tree mounts inside `#snipcart` (the div created by
   js/snipcart.js), so the prefix reaches all of it.

   NOT THEMED: Snipcart's stylesheet @imports Montserrat and Open Sans
   from fonts.bunny.net. The rules below stop them being used, but the
   import still fires. Removing it needs a self-hosted Snipcart theme
   build, which is a bigger change than this file is for.
   ============================================================ */

/* ---------- 1. Tokens ------------------------------------- */
#snipcart {
  /* Surfaces */
  --bgColor-default:      var(--bone);        /* cards, panels, item rows */
  --bgColor-alt:          var(--sage-haze);   /* summary column, quiet rows */
  --bgColor-modal:        var(--cream);       /* the cart / checkout canvas */
  --bgColor-modalVeil:    rgba(38, 48, 42, 0.38);   /* was white 70% — dims the page so the panel reads as foreground */

  /* Text */
  --color-default:        var(--ink);
  --color-alt:            var(--ink-soft);
  --color-icon:           var(--forest);      /* was #0aa7f5 */

  /* Rules */
  --borderColor-default:  var(--line);

  /* Links */
  --color-link:           var(--forest);
  --color-link-hover:     var(--clay-deep);
  --color-link-focus:     var(--clay-deep);
  --color-link-active:    var(--forest-deep);
  --borderColor-link:         var(--forest);
  --borderColor-link-hover:   var(--clay-deep);
  --borderColor-link-focus:   var(--clay-deep);
  --borderColor-link-active:  var(--forest-deep);
  --bgColor-link-focus:   transparent;
  --shadow-link-focus:    0 0 0 3px rgba(176, 138, 90, 0.28);

  /* Primary button — matches .btn on the site */
  --color-buttonPrimary:              var(--cream);
  --bgColor-buttonPrimary:            var(--forest);
  --borderColor-buttonPrimary:        var(--forest);
  --color-buttonPrimary-hover:        var(--cream);
  --bgColor-buttonPrimary-hover:      var(--forest-deep);
  --borderColor-buttonPrimary-hover:  var(--forest-deep);
  --color-buttonPrimary-focus:        var(--cream);
  --bgColor-buttonPrimary-focus:      var(--forest);
  --borderColor-buttonPrimary-focus:  var(--forest);
  --color-buttonPrimary-active:       var(--cream);
  --bgColor-buttonPrimary-active:     var(--forest-deep);
  --borderColor-buttonPrimary-active: var(--forest-deep);
  --color-buttonPrimary-disabled:     var(--cream);
  --bgColor-buttonPrimary-disabled:   var(--sage);
  --borderColor-buttonPrimary-disabled: var(--sage);
  --shadow-buttonPrimary-hover:  0 6px 14px -8px rgba(38, 48, 42, 0.55);
  --shadow-buttonPrimary-focus:  0 0 0 3px rgba(176, 138, 90, 0.35);
  --shadow-buttonPrimary-active: none;

  /* Secondary button — matches .btn--secondary */
  --color-buttonSecondary:              var(--forest);
  --bgColor-buttonSecondary:            transparent;
  --borderColor-buttonSecondary:        var(--forest);
  --color-buttonSecondary-hover:        var(--cream);
  --bgColor-buttonSecondary-hover:      var(--forest);
  --borderColor-buttonSecondary-hover:  var(--forest);
  --color-buttonSecondary-focus:        var(--forest);
  --bgColor-buttonSecondary-focus:      var(--sage-haze);
  --borderColor-buttonSecondary-focus:  var(--forest);
  --color-buttonSecondary-active:       var(--cream);
  --bgColor-buttonSecondary-active:     var(--forest-deep);
  --borderColor-buttonSecondary-active: var(--forest-deep);
  --color-buttonSecondary-disabled:     var(--ink-soft);
  --bgColor-buttonSecondary-disabled:   var(--line-soft);
  --borderColor-buttonSecondary-disabled: var(--line);
  --shadow-buttonSecondary-hover:  0 6px 14px -8px rgba(38, 48, 42, 0.35);
  --shadow-buttonSecondary-focus:  0 0 0 3px rgba(176, 138, 90, 0.28);
  --shadow-buttonSecondary-active: none;

  /* Tag button (the outlined "apply discount" style) */
  --color-buttonTag:             var(--forest);
  --borderColor-buttonTag:       var(--forest);
  --color-buttonTag-hover:       var(--clay-deep);
  --borderColor-buttonTag-hover: var(--clay-deep);
  --color-buttonTag-focus:       var(--forest);
  --borderColor-buttonTag-focus: var(--clay-deep);
  --color-buttonTag-disabled:    var(--ink-soft);
  --borderColor-buttonTag-disabled: var(--line);
  --shadow-buttonTag-hover:  none;
  --shadow-buttonTag-focus:  0 0 0 3px rgba(176, 138, 90, 0.28);
  --shadow-buttonTag-active: none;

  /* Danger — "remove this item". Still reads as destructive on purpose:
     a warm brick that belongs to the palette, not Snipcart's pink. */
  --color-buttonDanger:             #8E3B2C;
  --bgColor-buttonDanger:           #F1E2DC;
  --borderColor-buttonDanger:       transparent;
  --color-buttonDanger-hover:       var(--cream);
  --bgColor-buttonDanger-hover:     #8E3B2C;
  --borderColor-buttonDanger-hover: #8E3B2C;
  --color-buttonDanger-focus:       #8E3B2C;
  --bgColor-buttonDanger-focus:     #F1E2DC;
  --color-buttonDanger-active:      var(--cream);
  --bgColor-buttonDanger-active:    #75301F;
  --shadow-buttonDanger-hover: 0 6px 14px -8px rgba(38, 48, 42, 0.4);
  --shadow-buttonDanger-focus: 0 0 0 3px rgba(142, 59, 44, 0.25);

  /* Inputs — matches .field input on the contact form */
  --bgColor-input:              var(--bone);
  --color-input:                var(--ink);
  --borderColor-input:          var(--line);
  --color-inputLabel:           var(--forest);
  --color-inputPlaceholder:     #8A9086;
  --color-inputIcon:            var(--ink-soft);
  --bgColor-input-hover:        var(--bone);
  --color-input-hover:          var(--ink);
  --borderColor-input-hover:    var(--sage);
  --color-inputIcon-hover:      var(--forest);
  --shadow-input-hover:         none;
  --bgColor-input-focus:        var(--bone);
  --color-input-focus:          var(--ink);
  --borderColor-input-focus:    var(--clay);
  --color-inputIcon-focus:      var(--clay-deep);
  --shadow-input-focus:         0 0 0 3px rgba(176, 138, 90, 0.18);
  --bgColor-input-checked:      var(--forest);
  --borderColor-input-checked:  var(--forest);
  --color-input-checked:        var(--cream);
  --shadow-input-checked:       none;
  --bgColor-input-autofill:     var(--sage-haze);
  --bgColor-input-disabled:     var(--line-soft);
  --color-input-disabled:       var(--ink-soft);
  --borderColor-input-disabled: var(--line);
  --bgColor-input-error:        var(--bone);
  --color-input-error:          #8E3B2C;
  --borderColor-input-error:    #8E3B2C;
  --color-inputIcon-error:      #8E3B2C;

  /* Status */
  --color-success:       #3F6B45;
  --bgColor-success:     var(--sage-haze);
  --borderColor-success: var(--sage);
  --color-error:         #8E3B2C;
  --bgColor-error:       #F1E2DC;
  --bgColor-info:        var(--sage-haze);

  /* Step badge (the numbered circle beside "Billing") */
  --color-badge:                var(--forest);
  --bgColor-badge:              var(--bone);
  --borderColor-badge:          var(--sage);
  --color-badge-active:         var(--cream);
  --bgColor-badge-active:       var(--forest);
  --borderColor-badge-active:   var(--forest);
  --color-badge-disabled:       var(--ink-soft);
  --bgColor-badge-disabled:     var(--line-soft);
  --borderColor-badge-disabled: var(--line);

  /* Elevation */
  --shadow-default: var(--shadow-soft);
  --shadow-large:   0 2px 4px rgba(22, 24, 15, 0.05), 0 16px 40px rgba(22, 24, 15, 0.09);
  --shadow-tooltip: var(--shadow-soft);
}

/* ---------- 2. Typography --------------------------------- */
/* Snipcart hard-codes Open Sans at 14px for body and Montserrat for
   titles. Swap in the site's UI sans and display serif, and lift the
   base size from 14px to 15px — 14px reads noticeably smaller than
   anything else on the site. */
#snipcart.snipcart,
#snipcart .snipcart {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 400;
  color: var(--ink);
}

#snipcart .snipcart__font--secondary,
#snipcart .snipcart__font--subtitle,
#snipcart .snipcart__font--subtitle-small {
  font-family: var(--serif);
  letter-spacing: 0.01em;
}

/* Section headings: "Billing", "Order summary", "Shipping" */
#snipcart .snipcart__font--subtitle {
  font-size: 1.45rem;
  font-weight: 500;
  color: var(--forest);
}

#snipcart .snipcart__font--std   { font-size: 15px; line-height: 21px; }
#snipcart .snipcart__font--large { font-size: 17px; }
#snipcart .snipcart__font--xlarge { font-size: 19px; }

/* Prices and totals take the display serif, as they do on the product
   pages and the shop grid. */
#snipcart .snipcart-item-line__total-price,
#snipcart .snipcart-summary-fees__total .snipcart-summary-fees__amount,
#snipcart .snipcart-cart-summary-item__price {
  font-family: var(--serif);
  font-weight: 500;
  color: var(--forest);
}

/* Product names in the basket and the order summary */
#snipcart .snipcart-item-line__title,
#snipcart .snipcart-cart-summary-item__name {
  font-family: var(--serif);
  font-weight: 500;
  color: var(--forest);
}

/* ---------- 3. Shape -------------------------------------- */
/* Site buttons are pills; Snipcart's are 4px rectangles. */
#snipcart .snipcart-base-button {
  border-radius: var(--r-pill);
  border-width: 1.5px;
  /* the fallbacks are the token values, not near-misses: --dur-2 is 0.2s.
     A 0.25s fallback would have run off-scale on any page that loaded this
     file without urtica.css — and read as a fifth duration to anyone
     auditing the system from here. */
  transition: color var(--dur-2, 0.2s) var(--ease),
              background-color var(--dur-2, 0.2s) var(--ease),
              border-color var(--dur-2, 0.2s) var(--ease),
              box-shadow var(--dur-2, 0.2s) var(--ease),
              transform var(--dur-1, 0.15s) var(--ease);
}

#snipcart .snipcart-base-button__label {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: var(--tracking-caps);
}

/* Hover is a pointer privilege (motion v1.2 §3.2). The #snipcart prefix and
   the :not(:disabled) are unchanged — only the guard is new; the selector
   still has to outrank Snipcart's own later-injected stylesheet. */
@media (hover: hover) {
  #snipcart .snipcart-base-button:hover:not(:disabled) { transform: translateY(-1px); }
}
/* the house press: a finger gets the dip it never got from translateY(0) */
#snipcart .snipcart-base-button:active:not(:disabled) { transform: translateY(1px); }

/* Inputs match .field input: 1.5px hairline, 8px radius, bone fill. */
#snipcart .snipcart-input,
#snipcart .snipcart-input input,
#snipcart .snipcart-input select,
#snipcart .snipcart-form__select,
#snipcart #snipcart-billing-form .snipcart-input--readonly {
  border-radius: var(--r-md);
  border-width: 1.5px;
}

/* EVERY checkout field takes one face and one size — select on the element, not
   on the wrapper. Snipcart wraps most inputs in `.snipcart-input`, but routes
   the street-address and country typeaheads through `.snipcart-textbox`
   instead. An earlier version of this rule read `.snipcart-input input`, so it
   missed those two: they fell through to `.snipcart__font--secondary` on their
   wrapper and rendered in Spectral at 15px while the other seven sat in Hanken
   Grotesk at 16px. Verified on the live checkout — that mismatch is what the
   two-font screenshot showed.

   The face is var(--body), the same Newsreader that `.field input` uses on the
   contact form: typed input is serif everywhere else on this site, so the
   checkout now matches it rather than inventing a third convention.

   16px is a floor, not a preference — iOS Safari zooms the page when a focused
   field is smaller, and the address and country fields were below it at 15px. */
#snipcart input[type="text"],
#snipcart input[type="email"],
#snipcart input[type="tel"],
#snipcart input[type="number"],
#snipcart input[type="search"],
#snipcart input[type="password"],
#snipcart input:not([type]),
#snipcart select,
#snipcart textarea {
  font-family: var(--body);
  font-size: 16px;
}

#snipcart .snipcart-form__label {
  font-family: var(--sans);
  font-size: var(--fs-small);
  font-weight: 600;
}

/* Two elements set `font-family: Open Sans` on themselves rather than
   inheriting it, so the root rule above cannot reach them. The test
   banner keeps its orange — that warning is meant to be loud, and it
   disappears the moment the Live API key goes in. */
#snipcart .snipcart-modal__close,
#snipcart .snipcart-test-banner__message {
  font-family: var(--sans);
}

/* Cards: hairline plus the site's soft shadow, not Snipcart's hard drop. */
#snipcart .snipcart-item-line,
#snipcart .snipcart-cart-summary__content,
#snipcart .snipcart-payment-card,
#snipcart .snipcart-shipping-rates-list-item {
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
}

#snipcart .snipcart-featured-payment-methods { border-top-color: var(--line); }

/* Focus visibility — Snipcart kills the outline on its own buttons and
   relies on a box-shadow, which the tokens above supply. Restore a real
   ring everywhere else so keyboard users can see where they are. */
#snipcart .snipcart__actions--link:focus-visible,
#snipcart button:focus-visible,
#snipcart a:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 2px;
}

/* Motion: respect the same preference the rest of the site does. */
@media (prefers-reduced-motion: reduce) {
  @media (hover: hover) {
    #snipcart .snipcart-base-button:hover:not(:disabled) { transform: none; }
  }
  /* the press survives — it just arrives instantly. Reduced motion asks for
     no animation, not for a control that stops answering. */
  #snipcart .snipcart-base-button { transition: none; }
}

/* ---------- 5. Layer + touch targets (19 Aug 2026) --------- */

/* THE CART WAS UNCLOSABLE ON A PHONE. Snipcart mounts its modal as
   `.snipcart-modal__container`, position:fixed, z-index:20 — and #snipcart
   itself is static, so that 20 competes directly with the site header's 50
   in the root stacking context and loses. The header therefore painted over
   the top of the open cart, and the cart's ONE close control, the
   "Continue shopping" link at y=20, sat underneath it: elementFromPoint at
   the link's own centre returned the header's brand, so the tap never
   reached the link. 60 clears the header with room for anything that has
   to sit between them later.

   Verified against a real open cart, not from the stylesheet: the class
   names below were read off the live v3.9.0 DOM with an item in the
   basket. Same caution as the tokens above — re-check them if the pinned
   version moves. */
#snipcart .snipcart-modal__container { z-index: 60; }

/* "Continue shopping" was 179x20 — a text link with no padding at all.
   Padded to a real 44px target and pulled back by the same amount on the
   inline start, so the label stays exactly where it was against the
   header's 16px gutter. It stays a link; it does not become a button. */
#snipcart .snipcart-cart-header__close-button {
  min-height: 44px;
  padding: 0.75rem 0.5rem;
  margin-inline-start: -0.5rem;
}

/* Snipcart's icon buttons are sized by padding around a fixed 20px glyph:
   36x36 for remove (8px), 24x24 for the quantity steppers (2px). Both are
   below the 44px floor, and the steppers badly so. Squared off to 44 with
   the glyph left at 20px and centred, so the icon reads at exactly the
   size it did — only the reachable area grows. */
#snipcart .snipcart-item-line .snipcart-button-icon.is-danger,
#snipcart .snipcart-item-quantity .snipcart-button-icon {
  box-sizing: border-box;
  width: 44px; height: 44px;
  min-width: 44px; min-height: 44px;
  padding: 0;
  display: grid;
  place-items: center;
}

/* ---------- 6. The tax line (26 Aug 2026) ------------------ */

/* "Taxes — Calculated at checkout" NEVER resolves on this store. Ellie is not
   VAT registered, so Store Configurations → Taxes is empty; Snipcart returns
   `taxes.items: []` with status "Loaded" and leaves the placeholder standing.
   Verified on the live checkout at the payment step: Shipping had resolved to
   £5.50 and the Total was correct at £24.50, while Taxes still read "Calculated
   at checkout". A line telling a buyer that tax is yet to be worked out, on a
   price that is final, is wrong on the summary and worse on a completed order —
   and a trader who is not VAT registered must not present a tax line at all.

   Snipcart gives the row no class of its own; Subtotal, Shipping and Taxes are
   all bare `.snipcart-summary-fees__item`. So the two available signals are
   combined, and BOTH must hold:
     · the amount still carries `--regular`, which Snipcart puts on the
       placeholder and drops once a real figure arrives, and
     · the row sits immediately above the total.
   Taxes is the only row that satisfies both. Shipping is safe even before a
   rate is chosen, because Taxes sits between it and the total. If Snipcart ever
   returns a real tax figure the `--regular` class goes and the row reappears on
   its own, which is the behaviour we want if Ellie ever registers for VAT.

   :has() is unsupported in older browsers; there the row shows as it does now.
   This is a display fix only — it changes no total, and it cannot reach the
   confirmation email, which Snipcart renders server-side (dashboard → Email
   Templates). */
#snipcart .snipcart-summary-fees__item:has(.snipcart-summary-fees__amount.snipcart__font--regular):has(+ .snipcart-summary-fees__total) {
  display: none;
}
