/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ---------------------------------------------------------------------------
   Storefront
   Bootstrap 5.3 has no dashed-border utility, and the empty catalog state
   wants one. Everything else on the storefront uses stock Bootstrap.
   --------------------------------------------------------------------------- */
.border-dashed {
  border-style: dashed !important;
}

/* ---------------------------------------------------------------------------
   Cart drawer backdrop
   Bootstrap injects `.offcanvas-backdrop` from its JavaScript, and that bundle
   is no longer loaded — the drawer is offcanvas_controller.js now. The element
   is in the markup instead, and this is what shows and hides it.
   --------------------------------------------------------------------------- */
.offcanvas-backdrop {
  display: none;
}

.cart-drawer--open .offcanvas-backdrop {
  display: block;
  opacity: 0.5;
}

/* The line a customer has just added, tinted for as long as it takes to find
   it and then left alone. The drawer opening answers "did that work"; this
   answers "which one", which is the question with five things in the basket.

   The animation runs on its own: the drawer's markup is replaced on every
   basket change, so this element is new every time and a CSS animation on a
   newly inserted element plays without anything having to start it. */
.cart-line--added {
  animation: cart-line-added 2s ease-out;
}

@keyframes cart-line-added {
  from { background-color: rgba(25, 135, 84, 0.16); }
  to   { background-color: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .cart-line--added {
    animation: none;
  }
}

/* Named rather than built out of Bootstrap's badge utilities, which set colour
   and border with !important and so cannot be repainted by a shop's own
   stylesheet. Structure and a neutral default here; the colour is the shop's. */
.cart-line__flag {
  display: inline-block;
  margin-left: 0.25rem;
  padding: 0.15em 0.6em;
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  font-size: 0.7rem;
  font-weight: 400;
  vertical-align: middle;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Link color
   Bootstrap's default link blue reads as a stock framework and fights the
   near-black the rest of the interface uses. Overridden here rather than in
   the vendored bootstrap.min.css, which stays untouched so it can be replaced
   wholesale on an upgrade.

   Both variables are needed: a plain <a> reads --bs-link-color-rgb, while
   .nav-link, .btn-link and .page-link all derive from --bs-link-color. Setting
   only one leaves half the application blue.
   --------------------------------------------------------------------------- */
:root {
  --bs-link-color: #1a1a1a;
  --bs-link-color-rgb: 26, 26, 26;
  --bs-link-hover-color: #000000;
  --bs-link-hover-color-rgb: 0, 0, 0;
}

/* Color was doing the work of saying "this is a link" for the 58 places that
   opt out of the underline. Once it matches body text that cue is gone, so it
   comes back on hover and on keyboard focus — otherwise a link in a sentence
   is indistinguishable from the sentence.
   */
a.text-decoration-none:hover,
a.text-decoration-none:focus-visible {
  text-decoration: underline !important;
}

/* A value the shop needs and does not have — a missing SKU today, and whatever
   joins it later. Named for the meaning rather than the colour, so the next one
   does not invent its own.

   Not Bootstrap's .link-danger: that is #dc3545, which clears AA on a white row
   at 4.53:1 and fails at 4.04:1 on the grey a hovered row takes — which is
   exactly the moment somebody is reading it. This is Bootstrap's own red-600,
   6.50:1 and 5.50:1 in those two states. */
.link-missing {
  --bs-link-color-rgb: 176, 42, 55;
  --bs-link-hover-color-rgb: 136, 32, 43;
}

/* The sidebar and storefront nav sit on a light background where near-black on
   near-black gives no feedback at all. */
.nav-link:hover,
.nav-link:focus-visible {
  color: var(--bs-link-hover-color);
  background-color: rgba(0, 0, 0, 0.04);
}

.sidebar .nav-link.active {
  font-weight: 600;
  background-color: rgba(0, 0, 0, 0.06);
}

/* ---------------------------------------------------------------------------
   Home page slider
   Structure only. A shop's own stylesheet colours it — this is the part every
   clone needs and none of them should have to rebuild.

   The track is a scroll-snap strip, so with JavaScript off it stays a usable
   horizontally scrollable list of slides rather than collapsing to one. The
   Stimulus controller adds the dots, arrows and auto-advance on top.
   --------------------------------------------------------------------------- */
.slider {
  position: relative;
}

.slider__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.slider__track::-webkit-scrollbar {
  display: none;
}

/* The slide sets its own shape rather than inheriting the artwork's. Without
   this a square upload produces a square hero — as tall as the page is wide —
   and the shop discovers it only after uploading. object-fit crops to fit.
   Portrait on a phone, because a 3:1 band there is a letterbox slot with
   nothing legible in it. */
.slider__slide {
  position: relative;
  flex: 0 0 100%;
  scroll-snap-align: start;
  aspect-ratio: 4 / 5;
  min-height: 320px;
  max-height: 80svh;
  display: grid;
  /* One row that takes the slide's height rather than the image's. Without it
     the row is sized by the artwork's natural height, the box is sized by
     aspect-ratio, and the caption ends up below the visible slide — which
     looks exactly like a caption that failed to render. */
  grid-template-rows: 1fr;
}

@media (min-width: 768px) {
  .slider__slide {
    aspect-ratio: 3 / 1;
  }
}

/* One cell, so the picture fills the slide however the slide is shaped. */
.slider__slide > picture,
.slider__link {
  grid-area: 1 / 1;
  /* Grid items default to min-height: auto, which lets their content push the
     row taller than the track. */
  min-height: 0;
  min-width: 0;
}

.slider__slide > picture,
.slider__link {
  overflow: hidden;
}

.slider__link {
  display: block;
}

.slider__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.slider__controls {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
}

.slider__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #151515;
}

.slider__arrow:hover,
.slider__arrow:focus-visible {
  background: rgba(0, 0, 0, 0.08);
}

.slider__dots {
  display: flex;
  gap: 0.375rem;
  padding-inline: 0.25rem;
}

.slider__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 1px solid #151515;
  border-radius: 50%;
  background: transparent;
}

.slider__dot.is-current {
  background: #151515;
}

/* Every control is at least 44px of hit area even though the dot is 9px, which
   is the part that makes this usable on a phone. */
.slider__dot::before {
  content: "";
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.slider__dots { position: relative; }
.slider__dot { position: relative; }

/* ---------------------------------------------------------------------------
   Product quick view
   Structure only; a shop's own stylesheet colours it. Hidden with the `hidden`
   attribute rather than a class, so it is out of the accessibility tree and
   out of the tab order before anything is loaded into it — not merely
   invisible.
   --------------------------------------------------------------------------- */
.quick-view {
  position: fixed;
  inset: 0;
  z-index: 1060;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.quick-view[hidden] {
  display: none;
}

.quick-view__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
}

.quick-view__panel {
  position: relative;
  width: min(64rem, 100%);
  max-height: 90svh;
  overflow-y: auto;
  background: #fff;
  border-radius: 0.5rem;
  padding: 1.5rem;
}

.quick-view__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 1;
}

/* The detail column is laid out for a page two-thirds the width of a screen.
   Inside a dialog there is no sidebar competing with it, so the columns stack
   later than they would in the page. */
@media (max-width: 991.98px) {
  .quick-view__panel {
    padding: 1rem;
  }
}

/* ===========================================================================
   COOLIOH! BRAND
   Everything below this line is this shop's, not the template's. A clone that
   is not Coolioh replaces the whole block.

   The palette comes from the brand package's design-system.json, with two
   corrections made against the supplied logo and against WCAG 2.2 AA, which
   that document also requires. Both are recorded in docs/05-decisions.md.
   =========================================================================== */

:root {
  /* --- Ink and ground ---------------------------------------------------- */
  --co-ink: #151515;
  --co-ink-soft: #5b5b5b;
  --co-paper: #FFFDF6;
  --co-card: #FFFFFF;
  --co-line: rgba(21, 21, 21, 0.14);

  /* --- Brand colours ------------------------------------------------------
     `--co-red` is sampled from the logo (#F70000). It is a fill and display
     colour: at 4.16:1 on paper it carries large text and nothing smaller.
     `--co-red-aa` is the same red 4% darker, which is visually the same colour
     and clears 4.5:1 both as text on paper and under white text. Use the
     second anywhere words are involved.
     ---------------------------------------------------------------------- */
  --co-red: #F70000;
  --co-red-aa: #EA0000;
  --co-yellow: #FFD634;   /* pairs with ink only — white on it is 1.41:1 */
  --co-green: #20A65A;
  --co-green-aa: #1A8849; /* when white sits on it */
  --co-blue: #209EEB;
  --co-blue-aa: #197CB9;  /* white on the lighter blue is 2.94:1, which fails */
  --co-grape: #8C3FC7;
  --co-peach: #FF8C7A;
  --co-sky: #DDF2FF;

  /* --- Shape --------------------------------------------------------------
     The 2px offset shadow is the design system's, and it is a hard-edged
     sticker shadow rather than a blur — that is what makes the flat shapes
     read as cut out rather than as material.
     ---------------------------------------------------------------------- */
  --co-radius-sm: 8px;
  --co-radius: 16px;
  --co-radius-lg: 28px;
  --co-radius-pill: 999px;
  --co-shadow: 0 4px 0 rgba(21, 21, 21, 0.18);
  --co-keyline: 2px solid 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 ---------------------------------------------------------------
     --co-font-display is a token on purpose: the brand package specifies "a
     rounded, condensed comic display face" and supplies no file and no
     licence. Until one is chosen this falls through to the body stack, so
     headings are plain rather than wrong. Swapping it is one @font-face and
     one line here. See docs/05-decisions.md.
     ---------------------------------------------------------------------- */
  --co-font-body: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  --co-font-display: Fredoka, "Trebuchet MS", var(--co-font-body);
}

/* 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 above. */
: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 storefront's own ground. Scoped to a class rather than set on body,
   because the admin is staff-only and stays on the template's plain chrome —
   the same reasoning that keeps the logo out of the admin navbar.

   It replaces a `bg-white` utility that was on the layout's body tag. That
   utility carries !important, so a cream ground could not be set from here
   while it stayed. Cards are white, and cream is what separates them from the
   page. */
.co-storefront {
  background-color: var(--co-paper);
}

/* Headings get the display face; body copy never does. Every h1 and h2 on this
   storefront is a product name, a category name or a few words of hero copy,
   which is the "under eight words" rule the design system asks for. Anything
   longer that wants it has to say so with .co-display. */
.co-storefront h1,
.co-storefront h2,
.co-display {
  font-family: var(--co-font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* 700 is Fredoka's ceiling and the h1 wants all of it: the logo sits directly
   above it on every page, and a lighter heading underneath a very heavy
   wordmark reads as a mistake rather than as hierarchy. */
.co-storefront h1 {
  font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Product card
   Cream base, 16px radius, a flavour-coloured top rail, and a large
   transparent pack shot. Size, price and availability are always visible —
   the pack shots are cut out on transparent backgrounds, so without a defined
   panel behind them the products float on the page ground.
   --------------------------------------------------------------------------- */
.co-card {
  --co-rail: var(--co-ink);
  background: var(--co-card);
  border: 1px solid var(--co-line);
  border-top: 6px solid var(--co-rail);
  border-radius: var(--co-radius);
  overflow: hidden;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

/* The rail is the one place a product's category shows on the card, so it is
   keyed off the category rather than off a per-product colour the schema does
   not have. A category with no rule here keeps the ink default. */
.co-card[data-category="freeze-dried-candy"] { --co-rail: var(--co-blue); }
.co-card[data-category="peelable-gummies"]   { --co-rail: var(--co-green); }
.co-card[data-category="chamoy-gummies"]     { --co-rail: var(--co-red); }

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

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

/* A clean field rather than a tinted one. The design system offers both, and
   tinted loses: these bags are every colour there is, so a sky panel that
   flatters Rainbow Bursts swallows Polar Pops. The category colour is carried
   by the rail, where nothing has to compete with it. */
/* 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 — it looked like breathing room and was doing
   nothing. A square image fills this frame edge to edge, which is the point. */
.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. The panel colour is what stops the cut-out
   sitting on nothing. */
.co-card__media img {
  object-fit: contain;
}

.co-card__title {
  font-family: var(--co-font-display);
  font-weight: 700;
  line-height: 1.15;
}

.co-card__price {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Availability never rests on colour alone — each state carries its own word,
   which is the design system's accessibility rule and also what makes the
   states legible in a screenshot. There is no chip for an available product:
   the Add to bag button says that already. */
.co-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px;
  border-radius: var(--co-radius-pill);
  font-size: 0.8125rem;
  font-weight: 600;
  border: 1px solid var(--co-line);
}

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

/* ---------------------------------------------------------------------------
   Buttons
   The design system's shape: pill, 48px minimum, a black keyline, and a hard
   2px offset shadow rather than a blur — the shadow is what makes a flat shape
   read as cut out rather than as material. Pressing removes the offset, so the
   button physically 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-yellow);
  color: var(--co-ink);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--co-shadow);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}

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

.co-btn:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 rgba(21, 21, 21, 0.18);
}

/* Yellow is the primary because it is the only brand colour that carries ink
   at 12.97:1. Red is the accent, and it takes the AA variant because white
   text sits on it. */
.co-btn--fuego {
  background: var(--co-red-aa);
  color: #fff;
}

.co-btn--fuego:hover,
.co-btn--fuego:focus-visible {
  color: #fff;
}

.co-btn--quiet {
  background: transparent;
  box-shadow: none;
}

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

/* ---------------------------------------------------------------------------
   Storefront chrome
   --------------------------------------------------------------------------- */
.co-header {
  background: var(--co-card);
  border-bottom: 1px solid var(--co-line);
}

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

.co-header .nav-link.active {
  background: var(--co-yellow);
  color: var(--co-ink);
}

.co-hero {
  padding-block: var(--co-space-5);
}

.co-hero h1 {
  font-size: clamp(2.5rem, 6vw, 4rem);
  line-height: 1.02;
  max-width: 20ch;
  /* Without this the line breaks after "play" and leaves "with." alone on the
     second line. Ignored by browsers that do not support it, which get the
     ordinary break. */
  text-wrap: balance;
}

.co-hero__support {
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  color: var(--co-ink-soft);
  max-width: 30ch;
}

/* A category heading on the home page. The rule under it picks up the
   category's own colour, so the page is banded by category without a wall of
   coloured backgrounds. */
.co-section-head {
  border-bottom: 3px solid var(--co-rail, var(--co-ink));
  padding-bottom: var(--co-space-1);
}

.co-section-head[data-category="freeze-dried-candy"] { --co-rail: var(--co-blue); }
.co-section-head[data-category="peelable-gummies"]   { --co-rail: var(--co-green); }
.co-section-head[data-category="chamoy-gummies"]     { --co-rail: var(--co-red); }

.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.75;
}

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

.co-footer__tagline {
  font-family: var(--co-font-display);
  font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Slider, in Coolioh's clothes
   The structure above is the template's and stays untouched. This is only the
   part that makes it this shop's.
   --------------------------------------------------------------------------- */
.slider {
  background: var(--co-paper);
}

.slider__slide {
  border-bottom: 6px solid var(--co-yellow);
}

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

.slider__arrow {
  color: var(--co-ink);
}

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

.slider__dot {
  border-color: var(--co-ink);
}

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

/* ---------------------------------------------------------------------------
   Collection cards
   Same anatomy as a product card — cream field, coloured rail, 16px corner —
   because the two sit on the same page and reading as different systems would
   serve neither.
   --------------------------------------------------------------------------- */
.collection-card {
  background: var(--co-card);
  border-color: var(--co-line) !important;
  border-radius: var(--co-radius) !important;
  border-top: 6px solid var(--co-yellow) !important;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

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

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

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

.collection-card__title {
  font-family: var(--co-font-display);
  font-weight: 700;
}

/* Every buy button, wherever it appears — a card, the product page, or the
   quick view — is the same yellow pill with the ink keyline the rest of the
   shop uses. One rule rather than three, 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-weight: 600;
  box-shadow: var(--co-shadow);
}

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

.buy-button.btn:active {
  transform: translateY(4px);
  box-shadow: none;
}

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

/* The quantity stepper, wherever it appears — a card, the product page, or the
   quick view. Scoped to the component rather than to .co-card, so the control
   a shopper meets on the shop page is the control they meet in the modal. */
.quantity-stepper .btn-outline-secondary {
  border-color: var(--co-line);
  color: var(--co-ink);
  font-weight: 600;
}

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

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

/* The quick view, in Coolioh's clothes. Structure is the template's above. */
.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: 36px;
  height: 36px;
  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);
}

/* The dialog is its own surface, so headings inside it take the display face
   the same way they do on the page. */
.quick-view__panel h1 {
  font-family: var(--co-font-display);
  font-weight: 700;
}

/* The basket drawer's confirmation, in Coolioh's colours. The template tints
   the new line Bootstrap green and labels it in a plain pill; here the tint is
   the brand yellow and the pill is a sticker like every other pill in the
   shop. Same markup, same behaviour — only the paint is ours. */
@keyframes cart-line-added {
  from { background-color: rgba(255, 214, 52, 0.55); }
  to   { background-color: transparent; }
}

.cart-line__flag {
  background: var(--co-yellow);
  color: var(--co-ink);
  border: var(--co-keyline);
  font-family: var(--co-font-display);
  font-weight: 600;
}
