/* COOLIOH! — the shop's own stylesheet.
 *
 * The only stylesheet this shop writes. foundation.css, storefront.css and
 * admin.css belong to the template and are copied in unchanged on an update;
 * verify fails if one of them has been edited here.
 *
 * Loaded last, and only on storefront and account pages. The admin never sees
 * it, which is why staff meet the same interface in every shop — and it holds
 * structurally rather than by convention, because this file is not on those
 * pages at all.
 *
 * ---------------------------------------------------------------------------
 * THE COOLIOH-VERSE
 *
 * The design system is a sticker aesthetic turned up: flat brand colour, a 3px
 * ink keyline, a hard offset shadow rather than a blur, generous radii, and a
 * page ground that changes colour as you move between the shop's four worlds.
 *
 * The restraint rule from the earlier system survives and matters more here,
 * not less: the treatment is loud, and a checkout is seven panels and fourteen
 * fields. Applied to all of them it stops being emphasis and becomes noise. So
 * the catalog shouts and the money pages stay quiet — see the note down there.
 * --------------------------------------------------------------------------- */

/* ===========================================================================
   PALETTE

   The colours come from the Coolioh-Verse design and every one of them has
   been checked against WCAG 2.2 AA on this page ground, because five of the
   seven do not pass on their own:

     red    #E8262D  4.24:1 on paper — fails as text, and white on it is 4.42
     yellow #FFC907  1.48:1 — a fill and nothing else, ink only
     orange #FF7A00  2.51:1 — a fill, ink only
     green  #1FA34F  3.14:1 — large text only
     blue   #23B5E0  2.30:1 — a fill, ink only
     purple #7C4DFF  4.62:1 — the only one clean both ways
     pink   #F43F7E  3.44:1 — large only, and NEITHER ink nor white clears it

   On the marketing site this never surfaced: those colours only ever appear
   as 4rem display type, where 3:1 is the bar. In a shop they carry prices,
   chips and links, so each fill colour has an `-aa` companion darkened until
   words clear 4.5:1. Use the base to fill, the -aa whenever there are words.
   Derived rather than eyeballed; re-derive if you change a base.
   =========================================================================== */

:root {
  /* --- Ink and ground ---------------------------------------------------- */
  --co-ink: #33220F;          /* warm near-black, 14.63:1 on paper */
  --co-ink-soft: #82715A;     /* was #8A7860 at 4.08:1, which failed */
  --co-paper: #FFFAEC;
  --co-card: #FFFFFF;
  --co-cream: #FFF3CE;
  --co-line: rgba(51, 34, 15, 0.16);

  /* --- The four worlds ----------------------------------------------------
     Each world owns a fill colour and a page tint. The tint is what the body
     morphs to as a section scrolls past; ink clears 12.9:1 on all of them. */
  --co-bg-fuegos: #FFE9D2;
  --co-bg-peelz: #FFF4C4;
  --co-bg-polar: #E3F6FD;
  --co-bg-vault: #F0E9FF;

  /* --- Brand colours, fill / text ---------------------------------------- */
  --co-red: #E8262D;
  --co-red-aa: #DF242B;
  --co-yellow: #FFC907;       /* ink only — white on it is 1.54:1 */
  --co-orange: #FF7A00;
  --co-orange-aa: #B85800;
  --co-green: #1FA34F;
  --co-green-aa: #198440;
  --co-blue: #23B5E0;
  --co-blue-aa: #187D9B;
  --co-purple: #7C4DFF;       /* clean as text and under white */
  --co-pink: #F43F7E;
  --co-pink-aa: #CF366B;

  /* --- Shape --------------------------------------------------------------
     The keyline goes 2px -> 3px and the shadow 4px -> 6px, hard-edged rather
     than blurred. That pair is most of the difference between the old shop and
     this one, and both are read by template components through the token
     contract below, so setting them here moves the whole storefront. */
  --co-radius-sm: 10px;
  --co-radius: 18px;
  --co-radius-lg: 28px;
  --co-radius-pill: 999px;
  --co-keyline: 3px solid var(--co-ink);
  --co-shadow: 6px 6px 0 var(--co-ink);
  --co-shadow-ink: rgba(51, 34, 15, 0.85);
  --co-shadow-sm: 4px 4px 0 var(--co-ink);

  /* --- Spacing, on an 8px base ------------------------------------------- */
  --co-space-1: 8px;
  --co-space-2: 16px;
  --co-space-3: 24px;
  --co-space-4: 32px;
  --co-space-5: 48px;

  /* --- Type ---------------------------------------------------------------
     Luckiest Guy for display and Permanent Marker for the hand-written labels,
     both self-hosted in fonts.css on the same terms as Inter — a stylesheet
     from Google would send every visitor's IP there before a pixel is painted,
     and lib/verify/checks/assets.rb fails the run for any third-party fetch.

     Fredoka stays in the chain. It is already self-hosted, it is the nearest
     rounded face to Luckiest Guy, and it is what renders if the display woff2
     has not been fetched yet — headings stay in the family rather than falling
     all the way to Arial. */
  --co-font-body: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  --co-font-display: "Luckiest Guy", Fredoka, "Arial Rounded MT Bold", var(--co-font-body);
  --co-font-marker: "Permanent Marker", Fredoka, var(--co-font-body);
}

/* ---------------------------------------------------------------------------
   The template's token contract, in Coolioh's values
   foundation.css declares these with neutral defaults and the template's own
   components read them. Setting them here is what makes a shared component
   arrive already wearing the brand, without the template ever knowing a --co-
   variable exists. It is also what dresses the forty-odd views nobody hand
   edits — checkout, account, devise, errors — for free.
   --------------------------------------------------------------------------- */
:root {
  --shop-ink: var(--co-ink);
  --shop-ink-soft: var(--co-ink-soft);
  --shop-paper: var(--co-paper);
  --shop-card: var(--co-card);
  --shop-line: var(--co-line);

  /* Yellow fills, red-aa carries words. Ink is what sits on the yellow: white
     on it is 1.54:1, so the contract's "accent-ink" is the near-black. */
  --shop-accent: var(--co-yellow);
  --shop-accent-aa: var(--co-red-aa);
  --shop-accent-ink: var(--co-ink);

  --shop-radius-sm: var(--co-radius-sm);
  --shop-radius: var(--co-radius);
  --shop-radius-lg: var(--co-radius-lg);
  --shop-radius-pill: var(--co-radius-pill);
  --shop-keyline: var(--co-keyline);
  --shop-shadow: var(--co-shadow);

  --shop-font-body: var(--co-font-body);
  --shop-font-display: var(--co-font-display);
}

/* Bootstrap's own variables, so stock components inherit the brand rather than
   being overridden one at a time. The vendored bootstrap.min.css stays
   untouched, as with the link colours in foundation.css. */
:root {
  --bs-body-bg: var(--co-paper);
  --bs-body-color: var(--co-ink);
  --bs-border-radius: var(--co-radius-sm);
  --bs-border-radius-lg: var(--co-radius);
  --bs-border-radius-xl: var(--co-radius-lg);
  --bs-border-radius-pill: var(--co-radius-pill);
}

body { color: var(--co-ink); }

/* ---------------------------------------------------------------------------
   The world morph
   Sections carry data-world; world_controller.js mirrors the one in view onto
   <body>, and the ground cross-fades. Scoped to .storefront so the admin keeps
   the template's plain chrome, and the transition is on background-color only
   — transitioning `all` here repaints every descendant on every scroll.
   --------------------------------------------------------------------------- */
.storefront {
  background-color: var(--co-paper);
  transition: background-color 0.7s ease;
}

.storefront[data-world="fuegos"] { background-color: var(--co-bg-fuegos); }
.storefront[data-world="peelz"]  { background-color: var(--co-bg-peelz); }
.storefront[data-world="polar"]  { background-color: var(--co-bg-polar); }
.storefront[data-world="vault"]  { background-color: var(--co-bg-vault); }

@media (prefers-reduced-motion: reduce) {
  .storefront { transition: none; }
}

/* ---------------------------------------------------------------------------
   Type
   Headings take the display face; body copy never does. Luckiest Guy is all
   caps by design and has no lowercase to speak of, so it gets letter-spacing
   rather than the negative tracking a rounded sans wants.
   --------------------------------------------------------------------------- */
.storefront h1,
.storefront h2,
.co-display {
  font-family: var(--co-font-display);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: 0.5px;
}

.storefront h1 { line-height: 1.02; }

/* The hand-written voice: eyebrows, taglines, the small asides. Never for
   anything longer than a few words — it is a marker pen, not a typeface. */
.co-marker {
  font-family: var(--co-font-marker);
  font-weight: 400;
}

/* Candy letter colours, for a headline that changes colour word by word. Each
   is display-size only, which is the one place the base fills are legal. */
.c-red { color: var(--co-red); }
.c-orange { color: var(--co-orange); }
.c-green { color: var(--co-green); }
.c-blue { color: var(--co-blue); }
.c-purple { color: var(--co-purple); }
.c-pink { color: var(--co-pink); }

/* ---------------------------------------------------------------------------
   Announcement ticker
   Two identical runs of spans inside the track, translated -50%: the second
   run is where the first came from, so the loop has no seam. aria-hidden in
   the markup — it is decorative and a screen reader reading it on a loop is
   an obstacle rather than information.
   --------------------------------------------------------------------------- */
.co-ticker {
  background: var(--co-yellow);
  border-bottom: var(--co-keyline);
  overflow: hidden;
  white-space: nowrap;
}

.co-ticker__track {
  display: inline-block;
  padding: 7px 0;
  animation: co-tick 30s linear infinite;
}

.co-ticker__track span {
  font-family: var(--co-font-display);
  font-size: 0.92rem;
  color: var(--co-ink);
  margin: 0 24px;
  letter-spacing: 1px;
}

@keyframes co-tick {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ---------------------------------------------------------------------------
   Mega marquee
   The full-bleed band between sections. Same seamless trick as the ticker at
   a larger size, tilted a degree so it reads as a sticker slapped on rather
   than as a rule.
   --------------------------------------------------------------------------- */
/* The clip. The band inside is deliberately wider than the page and tilted;
   without this its overhang becomes horizontal page scroll. Kept off the page
   itself because overflow-x there makes the document a scroll container and
   breaks position: sticky inside it. */
.co-marquee-clip {
  overflow: hidden;
  margin-block: var(--co-space-5);
}

.co-marquee {
  overflow: hidden;
  white-space: nowrap;
  border-block: var(--co-keyline);
  transform: rotate(-1deg);
  /* The rotation pulls the ends inward, so it is oversized to keep the band
     bleeding past both edges of the viewport. The clip above absorbs it. */
  width: 104%;
  margin-inline: -2%;
}

.co-marquee__track {
  display: inline-block;
  padding: 10px 0;
  animation: co-tick 24s linear infinite;
}

.co-marquee__track span {
  font-family: var(--co-font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.9rem);
  margin: 0 22px;
  letter-spacing: 1px;
}

.co-marquee--red { background: var(--co-red); color: var(--co-card); }
.co-marquee--purple { background: var(--co-purple); color: var(--co-card); }
.co-marquee--yellow { background: var(--co-yellow); color: var(--co-ink); }

@media (prefers-reduced-motion: reduce) {
  .co-ticker__track,
  .co-marquee__track { animation: none; }
}

/* ---------------------------------------------------------------------------
   Scallop
   The wavy edge between a section and the next. A repeating radial gradient
   rather than an image: it recolours with the world morph, costs no request,
   and scales without going soft.
   --------------------------------------------------------------------------- */
.co-scallop {
  height: 22px;
  background-image: radial-gradient(circle at 14px 0, transparent 14px, var(--co-ink) 14px);
  background-size: 28px 22px;
  background-repeat: repeat-x;
  /* Only the 3px lip is wanted, not a solid ink band. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0 3px, transparent 3px);
  mask-image: linear-gradient(to bottom, #000 0 3px, transparent 3px);
}

/* ---------------------------------------------------------------------------
   Header
   --------------------------------------------------------------------------- */
.co-header {
  background: var(--co-paper);
  border-bottom: var(--co-keyline);
  transition: background-color 0.7s ease;
}

.co-header .navbar-brand img { transition: transform 0.2s ease; }
.co-header .navbar-brand:hover img { transform: rotate(-3deg) scale(1.06); }

.co-header .nav-link {
  font-weight: 900;
  border-radius: var(--co-radius-pill);
  padding-inline: var(--co-space-2);
}

.co-header .nav-link:hover,
.co-header .nav-link:focus-visible {
  text-decoration: underline wavy var(--co-red) 3px;
  text-underline-offset: 7px;
  background: transparent;
}

.co-header .nav-link.active {
  text-decoration: underline wavy var(--co-yellow) 3px;
  text-underline-offset: 7px;
}

/* --- Mega menu ------------------------------------------------------------
   Opens on hover for a pointer and on focus for a keyboard, which is the pair
   that makes it reachable without JavaScript. It is a plain list underneath:
   with no CSS at all the four links are still in the document, in order. */
.co-mega {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  min-width: 300px;
  padding: var(--co-space-1);
  background: var(--co-card);
  border: var(--co-keyline);
  border-radius: var(--co-radius);
  box-shadow: var(--co-shadow);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s ease, transform 0.16s ease;
  z-index: 60;
}

.co-has-mega { position: relative; }

.co-has-mega:hover .co-mega,
.co-has-mega:focus-within .co-mega {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.co-mega a {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 4px var(--co-space-1);
  align-items: center;
  padding: var(--co-space-1) var(--co-space-2);
  border-radius: var(--co-radius-sm);
  font-weight: 900;
  text-decoration: none;
  color: var(--co-ink);
}

.co-mega a small {
  grid-column: 2;
  font-weight: 400;
  color: var(--co-ink-soft);
}

.co-mega a i {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--co-ink);
}

.co-mega a:hover,
.co-mega a:focus-visible { background: var(--co-cream); }

@media (max-width: 767.98px) {
  /* Collapsed into the burger menu, where an absolutely positioned panel has
     nothing to hang off. It becomes an indented list. */
  .co-mega {
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    border: 0;
    box-shadow: none;
    padding-left: var(--co-space-3);
    min-width: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .co-header .navbar-brand img,
  .co-mega { transition: none; }
}

/* ---------------------------------------------------------------------------
   Hero
   Nearly a full screen, left-aligned, with the pack shots clustered on the
   right of the words rather than around them. Everything below it is either a
   colour wash, an outline or a motion — none of it load-bearing, all of it
   switched off for anyone who has asked for less movement.
   --------------------------------------------------------------------------- */
.co-hero {
  position: relative;
  min-height: 92vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  padding-block: var(--co-space-5) 100px;
}

/* Two soft colour washes drifting behind everything. Radial gradients rather
   than images: they cost no request, scale to any viewport, and are the one
   place in this design where an edge is allowed to be soft. */
.co-hero::before,
.co-hero::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  z-index: 0;
  filter: blur(2px);
  opacity: 0.55;
  pointer-events: none;
}

.co-hero::before {
  width: 62vw;
  height: 62vw;
  right: -18vw;
  top: -22vw;
  background: radial-gradient(circle at 35% 35%, var(--co-yellow), var(--co-orange) 55%, transparent 72%);
  animation: co-blob-drift 16s ease-in-out infinite alternate;
}

.co-hero::after {
  width: 46vw;
  height: 46vw;
  left: -16vw;
  bottom: -20vw;
  background: radial-gradient(circle at 60% 40%, var(--co-blue), var(--co-pink) 60%, transparent 75%);
  animation: co-blob-drift 20s ease-in-out infinite alternate-reverse;
}

@keyframes co-blob-drift {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(-6vw, 5vw) scale(1.15) rotate(12deg); }
}

.co-hero__inner {
  position: relative;
  z-index: 2;
  max-width: 820px;
}

/* Green rather than yellow, and a stamped rectangle rather than a pill, so it
   reads as a sticker slapped on the page. White on the base green is 3.28:1
   and fails, so this takes the darkened companion. */
.co-hero__kicker {
  display: inline-block;
  transform: rotate(-2deg);
  padding: 6px 18px;
  background: var(--co-green-aa);
  color: var(--co-card);
  border: 2.5px solid var(--co-ink);
  border-radius: 6px;
  box-shadow: 3px 3px 0 var(--co-shadow-ink);
  font-size: 1.05rem;
}

.co-hero h1 {
  font-size: clamp(3rem, 9.5vw, 5.5rem);
  margin: 26px 0 10px;
  max-width: none;
  text-wrap: balance;
}

/* The candy lettering: each word outlined in ink and dropped onto a hard
   offset shadow. inline-block because a text stroke on an inline box breaks
   across line boxes, and because each word is animated on its own. */
.co-hero h1 .co-w {
  display: inline-block;
  -webkit-text-stroke: 2px var(--co-ink);
  text-shadow: 5px 5px 0 var(--co-shadow-ink);
  animation: co-pop-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

/* Staggered so the headline assembles itself rather than arriving at once.
   `backwards` on the shorthand above is what holds each word invisible until
   its own delay elapses. */
.co-hero h1 .co-w:nth-child(1) { animation-delay: 0.05s; }
.co-hero h1 .co-w:nth-child(2) { animation-delay: 0.15s; }
.co-hero h1 .co-w:nth-child(3) { animation-delay: 0.25s; }
.co-hero h1 .co-w:nth-child(4) { animation-delay: 0.35s; }
.co-hero h1 .co-w:nth-child(5) { animation-delay: 0.45s; }

@keyframes co-pop-in {
  from { opacity: 0; transform: scale(0.3) rotate(-8deg); }
  to   { opacity: 1; transform: scale(1) rotate(0); }
}

.co-hero__support {
  max-width: 52ch;
  margin: 12px 0 30px;
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  color: var(--co-ink-soft);
  font-weight: 800;
}

.co-hero__ctas {
  display: flex;
  gap: var(--co-space-2);
  flex-wrap: wrap;
}

.co-scroll-hint {
  margin-top: 44px;
  font-weight: 900;
  font-size: 0.9rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--co-ink-soft);
}

/* --- The floating pack shots ---------------------------------------------
   Clustered to the right of the words, each one bobbing on its own offset so
   they never move as a block. The drop shadow is hard-edged like every other
   shadow here — a blur would make them look like photographs rather than
   stickers. `--rot` is per-bag and lives in the keyframe so the rotation is
   not thrown away while it plays. */
.co-hero__bag {
  position: absolute;
  z-index: 1;
  width: clamp(110px, 16vw, 230px);
  pointer-events: none;
  filter: drop-shadow(6px 8px 0 rgba(51, 34, 15, 0.25));
  animation: co-floaty 6s ease-in-out infinite;
  will-change: transform;
}

.co-hero__bag img { width: 100%; height: auto; }

.co-hero__bag--1 { top: 6%;  right: 26%; --rot: -9deg; width: clamp(100px, 13vw, 190px); }
.co-hero__bag--2 { top: 56%; right: 30%; --rot: 6deg;  width: clamp(100px, 12vw, 180px); animation-delay: 1.2s; }
.co-hero__bag--3 { top: 14%; right: 3%;  --rot: 8deg;  animation-delay: 0.6s; }
.co-hero__bag--4 { top: 52%; right: 5%;  --rot: -6deg; animation-delay: 1.8s; }

@keyframes co-floaty {
  0%, 100% { transform: rotate(var(--rot)) translateY(0); }
  50%      { transform: rotate(var(--rot)) translateY(-18px); }
}

/* Below 760 the words centre and the bags stop competing with them: two go
   entirely and the survivors shrink and step back. */
@media (max-width: 760px) {
  .co-hero {
    min-height: 0;
    text-align: center;
    justify-content: center;
  }

  .co-hero__support { margin-inline: auto; }
  .co-hero__ctas { justify-content: center; }
}

@media (max-width: 700px) {
  .co-hero__bag--2,
  .co-hero__bag--4 { display: none; }

  .co-hero__bag { opacity: 0.85; width: 110px; }
}

/* Every one of the four motions above, off. The words keep their outline and
   their shadow — those are the design, not the animation. */
@media (prefers-reduced-motion: reduce) {
  .co-hero::before,
  .co-hero::after,
  .co-hero h1 .co-w,
  .co-hero__bag { animation: none; }
}

/* ---------------------------------------------------------------------------
   Section heads
   An eyebrow in the marker face on a coloured sticker, and a display heading
   under it. The eyebrow's colour is the world's, which is what bands the page
   by world without a wall of coloured backgrounds.
   --------------------------------------------------------------------------- */
.co-eyebrow {
  display: inline-block;
  padding: 3px var(--co-space-2);
  border: var(--co-keyline);
  border-radius: var(--co-radius-pill);
  background: var(--co-world, var(--co-yellow));
  color: var(--co-ink);
  font-family: var(--co-font-marker);
  transform: rotate(-1.5deg);
}

.co-section-head { margin-bottom: var(--co-space-4); }

.co-section-head h2 {
  font-size: clamp(1.7rem, 4vw, 2.6rem);
  margin-block: var(--co-space-1) 0;
}

/* --- The world colours, in one place -------------------------------------
   Keyed off the category slug rather than a per-product colour the schema
   does not have. A category with no rule here falls back to yellow, which is
   why a new category added in the admin looks deliberate rather than broken.
   `limited-edition` is a collection, not a category: the four worlds on the
   marketing site are three formats and one lifecycle state, and the data
   models that correctly, so the fourth rule is scoped to the collection. */
[data-world-key="freeze-dried-candy"] { --co-world: var(--co-red); --co-world-aa: var(--co-red-aa); }
[data-world-key="peelable-gummies"]   { --co-world: var(--co-green); --co-world-aa: var(--co-green-aa); }
[data-world-key="chamoy-gummies"]     { --co-world: var(--co-orange); --co-world-aa: var(--co-orange-aa); }
[data-world-key="limited-edition"]    { --co-world: var(--co-purple); --co-world-aa: var(--co-purple); }
[data-world-key="last-chance"]        { --co-world: var(--co-pink); --co-world-aa: var(--co-pink-aa); }
[data-world-key="fuegos"]             { --co-world: var(--co-orange); --co-world-aa: var(--co-orange-aa); }
[data-world-key="classic"]            { --co-world: var(--co-blue); --co-world-aa: var(--co-blue-aa); }

/* ---------------------------------------------------------------------------
   World cards
   The four doors on the home page. A big cut-out pack shot on the world's
   tint, the name in the world's colour, and the whole card a sticker.
   --------------------------------------------------------------------------- */
.co-world-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--co-card);
  border: var(--co-keyline);
  border-radius: var(--co-radius-lg);
  overflow: hidden;
  text-decoration: none;
  color: var(--co-ink);
  box-shadow: var(--co-shadow-sm);
  transition: transform 0.14s ease, box-shadow 0.14s ease;
}

.co-world-card:hover,
.co-world-card:focus-visible {
  transform: translate(-3px, -3px);
  box-shadow: var(--co-shadow);
  color: var(--co-ink);
}

.co-world-card__art {
  background: var(--co-world-tint, var(--co-cream));
  border-bottom: var(--co-keyline);
  padding: var(--co-space-3);
}

.co-world-card__art img {
  width: 100%;
  height: 190px;
  object-fit: contain;
}

.co-world-card__body { padding: var(--co-space-3); }

.co-world-card__body h3 {
  font-family: var(--co-font-display);
  font-weight: 400;
  color: var(--co-world-aa, var(--co-ink));
  margin-bottom: 4px;
}

.co-world-card__go {
  font-weight: 900;
  color: var(--co-world-aa, var(--co-ink));
}

[data-world-key="freeze-dried-candy"] .co-world-card__art { --co-world-tint: var(--co-bg-polar); }
[data-world-key="peelable-gummies"] .co-world-card__art   { --co-world-tint: var(--co-bg-peelz); }
[data-world-key="chamoy-gummies"] .co-world-card__art     { --co-world-tint: var(--co-bg-fuegos); }
[data-world-key="limited-edition"] .co-world-card__art    { --co-world-tint: var(--co-bg-vault); }

/* ---------------------------------------------------------------------------
   Product card
   The sticker treatment in full: white field, 3px keyline, hard offset shadow
   that deepens on hover, and a world-coloured rail across the top. The pack
   shots are cut out on transparent backgrounds, so the white field is what
   stops them floating on the page ground.
   --------------------------------------------------------------------------- */
.co-card {
  background: var(--co-card);
  border: var(--co-keyline);
  border-top: 8px solid var(--co-world, var(--co-ink));
  border-radius: var(--co-radius);
  overflow: hidden;
  box-shadow: var(--co-shadow-sm);
  transition: transform 0.14s ease, box-shadow 0.14s ease;
}

.co-card:hover,
.co-card:focus-within {
  transform: translate(-3px, -3px);
  box-shadow: var(--co-shadow);
}

/* No padding. Inside a Bootstrap `.ratio` the image is absolutely positioned
   against the padding box, so padding here changes the element's size and
   never insets the picture. */
.co-card__media { background: var(--co-card); }

/* contain, not cover: a pack shot with its top or bottom cropped off is worse
   than one with space around it. */
.co-card__media img {
  object-fit: contain;
  transition: transform 0.2s ease;
}

.co-card:hover .co-card__media img { transform: scale(1.04) rotate(-1.5deg); }

.co-card__title {
  font-family: var(--co-font-display);
  font-weight: 400;
  font-size: 1.15rem;
  line-height: 1.15;
  letter-spacing: 0.3px;
}

.co-card__price {
  font-family: var(--co-font-display);
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .co-card,
  .co-card__media img,
  .co-world-card { transition: none; }
  .co-card:hover,
  .co-card:focus-within,
  .co-world-card:hover,
  .co-world-card:focus-visible { transform: none; }
  .co-card:hover .co-card__media img { transform: none; }
}

/* ---------------------------------------------------------------------------
   Availability chips
   Availability never rests on colour alone — each state carries its own word
   and its own glyph. There is no chip for an available product: the Add to
   bag button says that already, and a chip on every card in a grid stops
   meaning anything.
   --------------------------------------------------------------------------- */
.co-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 12px;
  border: 2px solid var(--co-ink);
  border-radius: var(--co-radius-pill);
  font-size: 0.8125rem;
  font-weight: 900;
}

.co-chip--out_of_stock { background: var(--co-cream); color: var(--co-ink); }
.co-chip--coming_soon  { background: var(--co-yellow); color: var(--co-ink); }

/* ---------------------------------------------------------------------------
   Buttons
   Pill, 48px minimum, a 3px ink keyline, and a hard offset shadow rather than
   a blur — the shadow is what makes a flat shape read as cut out rather than
   as material. Pressing moves the button onto its own shadow, so it sinks.
   --------------------------------------------------------------------------- */
.co-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--co-space-1);
  min-height: 48px;
  padding: 0 var(--co-space-3);
  border: var(--co-keyline);
  border-radius: var(--co-radius-pill);
  background: var(--co-red-aa);
  color: var(--co-card);
  font-family: var(--co-font-display);
  font-weight: 400;
  letter-spacing: 0.5px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--co-shadow-sm);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* Red is the primary, and it is the darkened companion rather than the base:
   white on #E8262D is 4.42:1 and fails, on this it is 4.75:1. Visually the
   same red. */
.co-btn:hover,
.co-btn:focus-visible {
  color: var(--co-card);
  text-decoration: none;
  transform: translate(-2px, -2px) rotate(-1deg);
  box-shadow: 6px 6px 0 var(--co-ink);
  animation: co-jelly 0.45s ease;
}

.co-btn:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--co-ink);
  animation: none;
}

/* The squash-and-stretch on press. `scale` rather than `transform` on purpose:
   the hover rule above owns transform, and animating both from one property
   would make the two fight. */
@keyframes co-jelly {
  0%   { scale: 1 1; }
  30%  { scale: 1.12 0.88; }
  50%  { scale: 0.92 1.08; }
  70%  { scale: 1.05 0.95; }
  100% { scale: 1 1; }
}

/* Yellow is the secondary, and the only brand colour that carries ink at
   12.9:1 — every other one needs a darkened companion before a word can sit
   on it. */
.co-btn--yellow {
  background: var(--co-yellow);
  color: var(--co-ink);
}

.co-btn--yellow:hover,
.co-btn--yellow:focus-visible { color: var(--co-ink); }

@media (prefers-reduced-motion: reduce) {
  .co-btn { transition: none; }
  .co-btn:hover,
  .co-btn:focus-visible { transform: none; animation: none; }
  .co-btn:active { transform: none; }
}

/* Every buy button, wherever it appears — a card, the product page, the quick
   view, or the checkout. One rule rather than four, which is why the template
   gives the button a name instead of leaving it as Bootstrap's .btn-dark. */
.buy-button.btn {
  border: var(--co-keyline);
  border-radius: var(--co-radius-pill);
  background: var(--co-yellow);
  color: var(--co-ink);
  font-family: var(--co-font-display);
  font-weight: 400;
  letter-spacing: 0.5px;
  box-shadow: var(--co-shadow-sm);
}

.buy-button.btn:hover,
.buy-button.btn:focus-visible { background: var(--co-yellow); color: var(--co-ink); }
.buy-button.btn:active { transform: translate(4px, 4px); box-shadow: none; }

/* Raised means pressable, so a button that cannot be pressed sits flat. */
.buy-button.btn:disabled,
.buy-button.btn.disabled { box-shadow: none; cursor: not-allowed; }

.co-card .buy-button.btn { min-height: 40px; box-shadow: none; }

/* ---------------------------------------------------------------------------
   Reveal on scroll
   The class is added by reveal_controller.js when an element crosses into
   view. The resting state is defined only inside the motion query, so a
   visitor who asked for no motion — or has JavaScript off — never meets an
   element that is invisible waiting for a class that is not coming.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .co-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.5s ease, transform 0.5s ease;
  }

  .co-reveal.is-in {
    opacity: 1;
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------------- */
.co-footer {
  background: var(--co-ink);
  color: var(--co-paper);
  margin-top: var(--co-space-5);
}

.co-footer a { color: var(--co-paper); opacity: 0.78; }
.co-footer a:hover,
.co-footer a:focus-visible { opacity: 1; color: var(--co-paper); }

.co-footer h4 {
  font-family: var(--co-font-display);
  font-weight: 400;
  font-size: 1rem;
  letter-spacing: 1px;
  color: var(--co-yellow);
}

.co-footer__tagline { font-family: var(--co-font-marker); }

/* The scallop above the footer inverts: the lip is the footer's ink coming up
   into the page rather than the page's ink coming down. */
.co-footer .co-scallop {
  background-image: radial-gradient(circle at 14px 22px, var(--co-ink) 14px, transparent 14px);
  -webkit-mask-image: none;
  mask-image: none;
  height: 22px;
}

/* ---------------------------------------------------------------------------
   Slider, in Coolioh's clothes
   The structure is the template's and stays untouched. This is only paint.
   --------------------------------------------------------------------------- */
.slider { background: var(--co-paper); }
.slider__slide { border-bottom: 8px solid var(--co-yellow); }

.slider__controls {
  background: var(--co-paper);
  border: var(--co-keyline);
  box-shadow: var(--co-shadow-sm);
}

.slider__arrow { color: var(--co-ink); }
.slider__arrow:hover,
.slider__arrow:focus-visible { background: var(--co-yellow); }

.slider__dot { border-color: var(--co-ink); border-width: 2px; }
.slider__dot.is-current { background: var(--co-red); border-color: var(--co-red); }

/* ---------------------------------------------------------------------------
   Collection cards
   Same anatomy as a product card — they sit on the same page, and reading as
   two different systems would serve neither.
   --------------------------------------------------------------------------- */
.collection-card {
  background: var(--co-card);
  border: var(--co-keyline) !important;
  border-radius: var(--co-radius) !important;
  border-top: 8px solid var(--co-world, var(--co-yellow)) !important;
  box-shadow: var(--co-shadow-sm);
  transition: transform 0.14s ease, box-shadow 0.14s ease;
}

.collection-card:hover,
.collection-card:focus-visible {
  transform: translate(-3px, -3px);
  box-shadow: var(--co-shadow);
}

.collection-card__media { background: var(--co-card); }

.collection-card__title {
  font-family: var(--co-font-display);
  font-weight: 400;
  font-size: 1.15rem;
}

@media (prefers-reduced-motion: reduce) {
  .collection-card { transition: none; }
  .collection-card:hover,
  .collection-card:focus-visible { transform: none; }
}

/* ---------------------------------------------------------------------------
   Quick view
   Structure is the template's; this is the paint.
   --------------------------------------------------------------------------- */
.quick-view__panel {
  background: var(--co-card);
  border: var(--co-keyline);
  border-radius: var(--co-radius-lg);
  box-shadow: var(--co-shadow);
}

.quick-view__close {
  background: var(--co-paper);
  border: var(--co-keyline);
  border-radius: var(--co-radius-pill);
  color: var(--co-ink);
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.quick-view__close:hover,
.quick-view__close:focus-visible { background: var(--co-yellow); color: var(--co-ink); }

.quick-view__panel h1 { font-family: var(--co-font-display); font-weight: 400; }

/* ---------------------------------------------------------------------------
   Basket drawer
   The template tints a newly added line Bootstrap green and labels it in a
   plain pill; here the tint is brand yellow and the pill is a sticker like
   every other pill in the shop. Same markup, same behaviour — only the paint.
   --------------------------------------------------------------------------- */
@keyframes cart-line-added {
  from { background-color: rgba(255, 201, 7, 0.55); }
  to   { background-color: transparent; }
}

.cart-line__flag {
  background: var(--co-yellow);
  color: var(--co-ink);
  border: 2px solid var(--co-ink);
  font-family: var(--co-font-display);
  font-weight: 400;
}

.cart-line__media {
  border: 2px solid var(--co-line);
  border-radius: var(--co-radius-sm);
}

/* ---------------------------------------------------------------------------
   BASKET AND CHECKOUT — where the shouting stops.

   The pages that take money. The sticker treatment is loud, and a checkout is
   seven panels and fourteen fields; applied to all of them it stops being
   emphasis and becomes noise. So the panels are quiet, and the keyline and the
   shadow are spent on the two things a customer is actually looking for: the
   total, and the button that takes them onward.

   This restraint predates the redesign and survives it deliberately. The new
   system is louder than the one it replaces, which makes the argument
   stronger, not weaker.
   --------------------------------------------------------------------------- */

/* Two of Bootstrap's own variables, scoped to the storefront so the admin
   keeps the template's plain chrome. Both classes that read them set their
   property with !important, so this is the only way to reach them. */
.storefront {
  --bs-tertiary-bg-rgb: 255, 243, 206;
  --bs-tertiary-bg: #FFF3CE;
  --bs-secondary-rgb: 130, 113, 90;
  --bs-secondary-color-rgb: 130, 113, 90;
}

.storefront .card {
  background: var(--co-card);
  border: 2px solid var(--co-line);
  border-radius: var(--co-radius);
}

.storefront .card-header {
  background: transparent;
  border-bottom: 2px solid var(--co-line);
  font-family: var(--co-font-display);
  font-weight: 400;
}

.storefront .list-group-item {
  background: transparent;
  border-color: var(--co-line);
}

/* The one panel that gets the full treatment. */
.storefront .card.order-summary {
  border: var(--co-keyline);
  box-shadow: var(--co-shadow);
}

/* The number the customer came to this page to read. */
.order-totals__total {
  font-family: var(--co-font-display);
  font-weight: 400;
  font-size: 1.3rem;
  border-top-color: var(--co-ink) !important;
}

/* --- Fields ---------------------------------------------------------------
   A hairline at rest so an address form stays readable, and the ink keyline
   only on focus, where it marks the one field being filled. The yellow ring
   replaces Bootstrap's blue glow. */
.storefront .form-control,
.storefront .form-select {
  border: 2px solid var(--co-line);
  border-radius: var(--co-radius-sm);
  color: var(--co-ink);
}

.storefront .form-control:focus,
.storefront .form-select:focus {
  border-color: var(--co-ink);
  box-shadow: 0 0 0 3px rgba(255, 201, 7, 0.75);
}

.storefront .form-label { font-weight: 900; margin-bottom: 0.25rem; }
.storefront .form-text { color: var(--co-ink-soft); }

.storefront .form-check-input { border-color: rgba(51, 34, 15, 0.4); }

.storefront .form-check-input:checked {
  background-color: var(--co-red-aa);
  border-color: var(--co-red-aa);
}

.storefront .form-check-input:focus {
  border-color: var(--co-ink);
  box-shadow: 0 0 0 3px rgba(255, 201, 7, 0.75);
}

/* Choosing a shipping method changes the total, so the chosen row is worth
   showing as chosen rather than leaving it to a 16px dot. :has() does the
   work; where it is unsupported the row stays plain and the radio still says
   which is selected. */
.shipping-option:hover { background: var(--co-bg-polar); }

.shipping-option:has(.form-check-input:checked) {
  background: var(--co-bg-polar);
  box-shadow: inset 0 0 0 2px var(--co-line);
}

/* --- Secondary buttons --------------------------------------------------- */
.storefront .btn-outline-dark,
.storefront .btn-outline-secondary {
  border: 3px solid var(--co-ink);
  border-radius: var(--co-radius-pill);
  color: var(--co-ink);
  font-weight: 900;
}

.storefront .btn-outline-dark:hover,
.storefront .btn-outline-dark:focus-visible,
.storefront .btn-outline-secondary:hover,
.storefront .btn-outline-secondary:focus-visible {
  background: var(--co-bg-polar);
  border-color: var(--co-ink);
  color: var(--co-ink);
}

/* Out of stock is the one dark button that stays dark: it is not an invitation
   and must not look like one. */
.storefront .btn-dark:not(.buy-button) { border-radius: var(--co-radius-pill); }

/* --- Quantity stepper ---------------------------------------------------- */
.quantity-stepper .btn-outline-secondary {
  border-width: 2px;
  border-color: var(--co-line);
  color: var(--co-ink);
}

.quantity-stepper .btn-outline-secondary:hover,
.quantity-stepper .btn-outline-secondary:focus-visible {
  background: var(--co-bg-polar);
  border-color: var(--co-line);
  color: var(--co-ink);
}

.quantity-stepper .form-control {
  border-color: var(--co-line);
  font-variant-numeric: tabular-nums;
}

/* --- Coupon ---------------------------------------------------------------
   White on --co-green-aa is 4.58:1, which clears AA for the 12px text on this
   badge. Anything that darkens the green is safe; anything that lightens it is
   not, so check before changing it. */
.coupon-tag {
  background: var(--co-green-aa);
  border: 2px solid var(--co-ink);
  color: var(--co-card);
  font-family: var(--co-font-display);
  font-weight: 400;
}

/* --- Empty basket --------------------------------------------------------- */
.storefront .border-dashed {
  border-color: var(--co-line) !important;
  border-radius: var(--co-radius) !important;
  background: var(--co-card);
}

/* --- Alerts ---------------------------------------------------------------
   Ink on a brand tint, with the keyline that carries the rest of the shop.
   Text is ink in all three, which clears AA on every tint below. */
.storefront .alert {
  border: var(--co-keyline);
  border-radius: var(--co-radius);
  color: var(--co-ink);
}

.storefront .alert-warning { background: var(--co-bg-peelz); }
.storefront .alert-success { background: #D9F5E4; }
.storefront .alert-danger  { background: #FFE0E0; }

/* A fourth red, and the only place it is used. --co-red-aa clears AA on paper
   and on white but not on these tints, and an environment variable name a
   developer has to type correctly is the last thing to render at 4:1. */
.storefront .alert code { color: #C21D23; }
