/*
 * Cupped 2.0 design tokens + component classes.
 * Source of truth: Claude Design handoff (CLAUDE.md, 2026-06-27).
 * Import this first in base.html, before any other stylesheet.
 * Never use raw hex values or Bootstrap .btn/.card/.badge classes in templates —
 * reference a token or one of the component classes defined here instead.
 */

:root {
  /* Brand colours */
  --color-action: #D1461C;       /* Burnt orange — primary CTA only */
  --color-brand: #025F9C;        /* Steel blue — links, active states */
  --color-brand-dark: #013f68;   /* Hover on brand elements */
  --color-brand-fill: #025F9C;   /* Brand blue used as a FILL behind white text
                                    (badges, active pills, header band, stepper).
                                    Same as --color-brand in light; deepened in
                                    dark so white text keeps AA contrast. */
  --color-action-hover: #b83a17; /* Hover on CTA buttons */

  /* Surfaces */
  --color-bg: #F7F5F2;       /* Warm off-white — page background */
  --color-surface: #FFFFFF;  /* Cards, panels */
  --color-surface-2: #F0EDE9; /* Secondary surfaces, flavour tags */
  --color-dark: #0a1628;     /* Footer, dark hero overlays */

  /* Text */
  --color-ink: #1A1A1A;   /* Primary text */
  --color-ink-2: #555555; /* Body copy, secondary text */
  --color-ink-3: #999999; /* Muted, placeholders */

  /* Borders */
  --color-border: #E8E5E1;
  --color-border-strong: #CCCCCC;

  /* Semantic feedback (validation / success panels). Light values match the
     hardcoded hexes they replace, so existing forms look identical; the .dark
     block lifts them for legibility on dark surfaces. Use these instead of raw
     #hex in inline styles so feedback panels are theme-aware. */
  --color-danger: #dc2626;          /* error icon / accent */
  --color-danger-strong: #991b1b;   /* error heading / body text */
  --color-danger-border: #fca5a5;   /* error panel border */
  --color-danger-bg: #fef2f2;       /* error panel background */
  --color-success-strong: #065f46;  /* success heading / body text */
  --color-success-bg: #ecfdf5;      /* success panel background */

  /* Fonts */
  --font-ui: 'Nunito', sans-serif;
  --font-display: 'Playfair Display', serif;

  /* Spacing (8px base unit) */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-6: 48px;
  --space-8: 64px;
  --space-12: 96px;
  --space-16: 128px;

  /* Radius */
  --radius-sm: 6px;    /* Buttons, badges */
  --radius-md: 10px;   /* Cards */
  --radius-lg: 16px;   /* Panels, modals */
  --radius-full: 999px; /* Pills */

  /* Shadows */
  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.07), 0 0 1px rgba(0, 0, 0, 0.05);
  --shadow-card-hover: 0 8px 24px rgba(0, 0, 0, 0.12), 0 0 1px rgba(0, 0, 0, 0.06);
  --shadow-panel: 0 4px 16px rgba(0, 0, 0, 0.08);
}

/* ---------------------------------------------------------------------- */
/* Base resets / global rules                                            */
/* ---------------------------------------------------------------------- */

body {
  font-family: var(--font-ui);
  background: var(--color-bg);
  color: var(--color-ink);
}

p {
  text-wrap: pretty;
}

h1, h2, h3, h4 {
  text-wrap: balance;
}

a, button, input, select, textarea, [tabindex] {
  outline: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 3px;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding-inline: var(--space-4);
}

/* ---------------------------------------------------------------------- */
/* Type scale                                                             */
/* ---------------------------------------------------------------------- */

.text-display {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(36px, 5vw, 60px);
  line-height: 1.1;
}

.text-page-title {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 28px;
  color: var(--color-ink);
}

.text-section-title {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 20px;
  color: var(--color-ink);
}

.text-card-title {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 16px;
  color: var(--color-ink);
}

.text-body {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.65;
  color: var(--color-ink-2);
}

.text-label {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--color-brand);
}

/* ---------------------------------------------------------------------- */
/* Grid                                                                   */
/* ---------------------------------------------------------------------- */

.product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
@media (max-width: 900px) {
  .product-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .product-grid { grid-template-columns: 1fr; }
}

.roaster-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
@media (max-width: 900px) {
  .roaster-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .roaster-grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------- */
/* Carousel                                                               */
/* ---------------------------------------------------------------------- */

.carousel-wrapper {
  position: relative;
  padding: 0 28px;
  margin: 0 -28px;
}

.carousel-track {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 8px;
}
.carousel-track::-webkit-scrollbar { display: none; }

.carousel-track > * {
  flex: 0 0 calc((100% - 2 * var(--space-3)) / 3);
  scroll-snap-align: start;
  min-width: 0;
}

.carousel-btn {
  position: absolute;
  top: calc(50% - 16px);
  transform: translateY(-50%);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  font-size: 22px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
  box-shadow: var(--shadow-card);
  transition: box-shadow 0.2s, background 0.2s;
  color: var(--color-ink);
  padding: 0;
  border: 1px solid var(--color-border);
}
.carousel-btn:hover {
  box-shadow: var(--shadow-card-hover);
  background: var(--color-surface-2);
}
.carousel-btn--prev { left: 0; }
.carousel-btn--next { right: 0; }

@media (max-width: 900px) {
  .carousel-track > * {
    flex: 0 0 calc((100% - var(--space-3)) / 2);
  }
}
@media (max-width: 600px) {
  .carousel-track > * { flex: 0 0 85%; }
  .carousel-btn { display: none; }
  .carousel-wrapper { padding: 0; margin: 0; }
}

/* ---------------------------------------------------------------------- */
/* Buttons                                                                */
/* ---------------------------------------------------------------------- */

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  background: var(--color-action);
  color: #fff;
  border: none;
  padding: 12px 28px;
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s;
  text-decoration: none;
}
.btn-primary:hover { background: var(--color-action-hover); }
.btn-primary:disabled { background: var(--color-border-strong); cursor: not-allowed; }

.btn-primary--compact {
  padding: 8px 18px;
  font-size: 12px;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  background: transparent;
  color: var(--color-brand);
  border: 2px solid var(--color-brand);
  padding: 10px 24px;
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  text-decoration: none;
}
.btn-secondary:hover { background: var(--color-brand-fill); color: #fff; }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: transparent;
  color: var(--color-ink-2);
  border: none;
  padding: 10px 0;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.btn-ghost:hover { color: var(--color-ink); }

/* ---------------------------------------------------------------------- */
/* Badges & Tags                                                         */
/* ---------------------------------------------------------------------- */

.badge-roast {
  background: rgba(10, 22, 40, 0.75);
  color: #fff;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
}

/* Roaster stock page */
.stock-table th { border-bottom: 1px solid var(--color-border); }
.stock-table td {
  padding: 8px 12px 8px 0;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}
.stock-table__variant { color: var(--color-ink); font-weight: 600; }
.stock-table__price { color: var(--color-ink-3); }
.stock-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
}
.stock-pill--out { background: var(--color-danger-bg); color: var(--color-danger-strong); }
.stock-pill--low { background: #fef3c7; color: #92400e; }
.dark .stock-pill--low { background: rgba(217, 119, 6, 0.16); color: #fbbf24; }
.stock-pill--ok { background: var(--color-success-bg); color: var(--color-success-strong); }
.stock-pill--offline { background: var(--color-surface-2); color: var(--color-ink-3); }
.stock-saved-tick {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-success-strong);
}

.badge-soldout {
  background: var(--color-danger);
  color: #fff;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-left: 6px;
}

.tag-flavour {
  background: var(--color-surface-2);
  color: var(--color-ink-2);
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
}

.badge-sub {
  background: var(--color-brand-fill);
  color: #fff;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
}

.badge-independent {
  border: 1px solid var(--color-action);
  color: var(--color-action);
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
}

/* Variant for use over a dark hero overlay, where the orange-on-transparent
   default reads poorly against a dark photo background. */
.badge-independent--on-dark {
  border-color: #fff;
  color: #fff;
}

/* ---------------------------------------------------------------------- */
/* Forms & Filters                                                       */
/* ---------------------------------------------------------------------- */

.form-input,
.form-select {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--color-ink);
  outline: none;
  width: 100%;
}
.form-input:focus,
.form-select:focus {
  border-color: var(--color-brand);
  box-shadow: 0 0 0 3px rgba(2, 95, 156, 0.12);
}
.form-label {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-ink-2);
  margin-bottom: 6px;
  display: block;
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  background: var(--color-surface-2);
  color: var(--color-ink-2);
  border: none;
  padding: 8px 16px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.filter-pill--active,
.filter-pill[aria-current="true"] {
  background: var(--color-brand-fill);
  color: #fff;
}

.filter-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  position: sticky;
  top: 64px; /* sits just below .site-header, which is also sticky at top: 0 */
  z-index: 10;
  background: var(--color-bg);
  padding-block: var(--space-2);
}

/* Applied-filter chips (search results header) */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: var(--space-3);
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--color-surface-2);
  color: var(--color-ink-2);
  border: 1px solid var(--color-border);
  padding: 4px 12px;
  border-radius: var(--radius-full);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s;
}
.filter-chip:hover { background: var(--color-border); }
.filter-chip__x {
  font-size: 14px;
  line-height: 1;
  opacity: 0.6;
}
.filter-chip--clear {
  background: transparent;
  border-color: transparent;
  text-decoration: underline;
}
.filter-chip--clear:hover {
  background: transparent;
  color: var(--color-ink);
}

/* Results fade while an HTMX request is in flight (hx-indicator) */
#search-results.htmx-request {
  opacity: 0.5;
  transition: opacity 0.15s;
}

/* ---------------------------------------------------------------------- */
/* Compact page header (Browse / Search)                                 */
/* ---------------------------------------------------------------------- */

.page-header-compact {
  background: var(--color-brand-fill);
  min-height: 60px;
  display: flex;
  align-items: center;
  padding-block: var(--space-2);
  border-radius: var(--radius-lg);
}

/* ---------------------------------------------------------------------- */
/* Step indicator                                                        */
/* ---------------------------------------------------------------------- */

.steps {
  display: flex;
  align-items: center;
  gap: 0;
}
.step {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 14px;
  flex-shrink: 0;
}
.step--active { background: var(--color-action); color: #fff; }
.step--complete { background: var(--color-brand-fill); color: #fff; }
.step--future { background: var(--color-border); color: var(--color-ink-3); }
.step-line { flex: 1; height: 2px; background: var(--color-border); min-width: 32px; }

/* ---------------------------------------------------------------------- */
/* Product card                                                          */
/* ---------------------------------------------------------------------- */

.product-card {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: box-shadow 0.2s, transform 0.2s;
  display: flex;
  flex-direction: column;
}
.product-card:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
}
.product-card__media {
  position: relative;
}
.product-card__img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: var(--color-surface-2);
}
.product-card__badge {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
}
.product-card__body {
  padding: var(--space-2) var(--space-3) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.product-card__roaster {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-brand);
  text-decoration: none;
}
.product-card__roaster:hover { text-decoration: underline; }
.product-card__name {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 16px;
  color: var(--color-ink);
}
.product-card__rating {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-ink-2);
}
.product-card__rating-count {
  font-weight: 400;
  color: var(--color-ink-3);
}

.product-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.product-card__origin {
  font-size: 12px;
  color: var(--color-ink-3);
  margin-top: 2px;
}
.product-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-2);
  gap: var(--space-2);
}
.product-card__price {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 17px;
  color: var(--color-ink);
}

/* ---------------------------------------------------------------------- */
/* Roaster profile hero                                                  */
/* ---------------------------------------------------------------------- */

.roaster-hero {
  position: relative;
  height: 400px;
  display: flex;
  align-items: flex-end;
  background-color: var(--color-surface-2);
  background-size: cover;
  background-position: center;
  color: #fff;
}
.roaster-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(10, 22, 40, 0.55);
}
.roaster-hero__inner {
  position: relative;
  z-index: 1;
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--space-4);
  width: 100%;
}
.roaster-hero__location {
  color: rgba(255, 255, 255, 0.85);
}
.roaster-hero__badges {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

/* ---------------------------------------------------------------------- */
/* Roaster card (vertical, image-led)                                    */
/* ---------------------------------------------------------------------- */

.roaster-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: box-shadow 0.2s, transform 0.2s;
}
.roaster-card:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
}

/* The anchor wrapping the image — block so no extra whitespace */
.roaster-card__media {
  display: block;
  overflow: hidden;
  background: var(--color-surface-2);
  flex-shrink: 0;
}
.roaster-card__img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
  transition: transform 0.25s;
}
.roaster-card:hover .roaster-card__img {
  transform: scale(1.03);
}

.roaster-card__body {
  padding: var(--space-2) var(--space-3) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
}

/* Name + badge in one row */
.roaster-card__header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.roaster-card__name {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 17px;
  color: var(--color-ink);
  text-decoration: none;
  flex: 1 1 auto;
  line-height: 1.3;
}
.roaster-card__name:hover {
  color: var(--color-brand);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.roaster-card__location {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--color-ink-3);
}

/* Tagline: clamp to 2 lines */
.roaster-card__tagline {
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Meta row: rating + coffee count */
.roaster-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: 2px;
}
.roaster-card__meta-item {
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--color-ink-3);
}
.roaster-card__meta-item + .roaster-card__meta-item::before {
  content: "·";
  margin-right: var(--space-1);
}

/* Push the CTA to the bottom of the card */
.roaster-card__cta {
  margin-top: auto;
  padding-top: var(--space-1);
  font-size: 13px;
}

/* ---------------------------------------------------------------------- */
/* Navbar                                                                 */
/* ---------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--space-2) var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.site-header__logo {
  height: 32px;
  margin-right: var(--space-4);
  display: block;
}
.site-header__nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1;
}
.site-header__link {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-ink);
  text-decoration: none;
}
.site-header__link:hover,
.site-header__link--active {
  color: var(--color-brand);
}
.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.site-header__icon-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--color-ink);
  text-decoration: none;
}
.site-header__icon-link:hover { color: var(--color-brand); }
.site-header__cart-badge {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-full);
  background: var(--color-action);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}

.site-subnav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* ---------------------------------------------------------------------- */
/* Header search box                                                      */
/* ---------------------------------------------------------------------- */

/* Sits at the end of .site-header__nav on desktop; a copy lives inside
   the mobile nav panel. The input carries `field-compact` in the template
   to opt out of the site-wide square/large field override in base.html. */
.header-search {
  margin-left: auto;
}
.header-search__input {
  width: 200px;
  padding: 7px 14px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--color-ink);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
}
.header-search__input:focus {
  outline: 2px solid var(--color-brand);
  outline-offset: -1px;
  background: var(--color-surface);
}
.header-search__input::placeholder { color: var(--color-ink-3); }

/* ---------------------------------------------------------------------- */
/* Mobile navigation                                                      */
/* ---------------------------------------------------------------------- */

/* Hamburger toggle — hidden on desktop, shown under 900px where the
   inline nav disappears. The panel itself is toggled by JS via inline
   style.display (NOT the `hidden` attribute / Tailwind classes — see
   the display-class override gotcha). */
.site-header__menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-ink);
  padding: 0;
}
.site-header__menu-btn:hover { color: var(--color-brand); }

.mobile-nav {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-card);
  padding: var(--space-2) var(--space-4) var(--space-3);
}
.mobile-nav__search { margin-bottom: var(--space-1); }
.mobile-nav__search .header-search__input { width: 100%; }
.mobile-nav__link {
  display: block;
  padding: 12px 0;
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--color-border);
}
.mobile-nav__link:last-child { border-bottom: none; }
.mobile-nav__link:hover,
.mobile-nav__link--active { color: var(--color-brand); }

@media (max-width: 900px) {
  .site-header__inner { position: relative; }
  .site-header__nav { display: none; }
  .site-header__menu-btn { display: inline-flex; }
  /* Text links in the actions cluster (Account / Messages) move into the
     panel; icons (theme, sign-in, basket) stay in the bar. */
  .site-header__actions .site-header__link--collapsible { display: none; }
  .site-header__actions { margin-left: auto; }
}

/* ---------------------------------------------------------------------- */
/* Search filter drawer (mobile)                                          */
/* ---------------------------------------------------------------------- */

/* Below the search page's lg breakpoint (1024px, where its sidebar grid
   collapses) the filter form starts closed so results show first; the
   toggle button flips the --open modifier. Class-based, so resizing back
   to desktop always restores the sidebar. */
.search-filters-toggle {
  display: none;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1);
  padding: 10px 14px;
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.search-filters-toggle__chevron { transition: transform 0.15s; }
@media (max-width: 1023px) {
  .search-filters-toggle { display: flex; }
  .search-filters { display: none; }
  .search-filters--open { display: block; margin-top: var(--space-2); }
  .search-filters-toggle[aria-expanded="true"] .search-filters-toggle__chevron {
    transform: rotate(180deg);
  }
}

/* ---------------------------------------------------------------------- */
/* Toasts (flash messages + add-to-basket feedback)                       */
/* ---------------------------------------------------------------------- */

.toast-stack {
  position: fixed;
  top: 72px;
  right: var(--space-2);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-1);
  background: var(--color-dark);
  color: #fff;
  border-radius: var(--radius-md);
  padding: 12px 14px;
  box-shadow: var(--shadow-card-hover);
  font-size: 14px;
  line-height: 1.4;
  pointer-events: auto;
  animation: toast-in 0.18s ease-out;
}
.toast--success { background: #2e8a27; }
.toast--out {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.25s, transform 0.25s;
}
.toast a {
  color: #fff;
  font-weight: 700;
  text-decoration: underline;
}
.toast__close {
  background: none;
  border: none;
  color: inherit;
  opacity: 0.7;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  margin-left: auto;
}
.toast__close:hover { opacity: 1; }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------- */
/* Footer                                                                 */
/* ---------------------------------------------------------------------- */

.site-footer {
  background: var(--color-dark);
  color: rgba(255, 255, 255, 0.6);
}
.site-footer__inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--space-8) var(--space-4) var(--space-4);
}
.site-footer__tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(24px, 3vw, 36px);
  color: #fff;
  max-width: 700px;
}
.site-footer__columns {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-8);
}
@media (max-width: 700px) {
  .site-footer__columns { grid-template-columns: repeat(2, 1fr); }
}
.site-footer__heading {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  margin-bottom: var(--space-2);
}
.site-footer__link {
  display: block;
  color: rgba(255, 255, 255, 0.6);
  text-decoration: none;
  margin-top: var(--space-1);
}
.site-footer__link:hover { color: #fff; }
.site-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-8);
  padding-top: var(--space-3);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 13px;
}
.site-footer__social {
  display: flex;
  gap: var(--space-1);
}
.site-footer__social-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: background 0.15s;
}
.site-footer__social-icon:hover { background: var(--color-action); }

/* ---------------------------------------------------------------------- */
/* Small utility classes (replace one-off inline styles)                 */
/* ---------------------------------------------------------------------- */

.site-header__logo-img {
  height: 32px;
  display: block;
}

.btn-unstyled {
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
}

/* .flash-banner retired 2026-07-05 — flash messages now render as toasts
   (.toast / .toast-stack above); the same green lives on .toast--success. */

.is-disabled-link {
  cursor: not-allowed;
  opacity: 0.5;
}

/* ---------------------------------------------------------------------- */
/* Small utility classes (Roaster Profile / Product Detail cleanup)      */
/* Added in place of one-off inline style="" attributes that subagents   */
/* left behind — same rule as above: no inline styles in templates,      */
/* small reusable classes here instead.                                  */
/* ---------------------------------------------------------------------- */

.link-muted {
  color: var(--color-ink-2);
}

.text-on-dark {
  color: #fff;
}

.panel-promo {
  border: 1px solid var(--color-border);
  background: var(--color-surface-2);
}

.panel-card {
  background: var(--color-surface);
  box-shadow: var(--shadow-card);
}

.bg-surface {
  background: var(--color-surface);
}

.empty-state {
  border: 1px dashed var(--color-border-strong);
}

.list-divider {
  border-top: 1px solid var(--color-border);
}

.star-rating {
  color: var(--color-ink);
}

.star-empty {
  color: var(--color-border-strong);
}

.text-muted-3 {
  color: var(--color-ink-3);
}

.aspect-4-3 {
  aspect-ratio: 4 / 3;
}

.aspect-1-1 {
  aspect-ratio: 1 / 1;
}

/* ---------------------------------------------------------------------- */
/* Home hero — split layout: copy left, photo right (2026-07-05).        */
/* The photo (static/images/hero-beans-*.jpg) is light, so the hero sits */
/* on the page surface with ink text rather than the old dark slab.      */
/* ---------------------------------------------------------------------- */

.home-hero {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-4) 0 var(--space-2);
}
.home-hero__title { color: var(--color-ink); }
.home-hero__subtitle {
  color: var(--color-ink-2);
  margin-top: var(--space-3);
  max-width: 480px;
}
.home-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-6);
}
.home-hero__media img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-lg);
}
@media (max-width: 900px) {
  .home-hero {
    grid-template-columns: 1fr;
    gap: var(--space-4);
    padding-top: var(--space-2);
    text-align: center;
  }
  .home-hero__subtitle { margin-inline: auto; }
  .home-hero__actions { justify-content: center; }
  /* Full-bleed photo: escape <main>'s 1rem inline padding. */
  .home-hero__media {
    margin-inline: -1rem;
  }
  .home-hero__media img {
    aspect-ratio: 4 / 3;
    border-radius: 0;
  }
}

/* Light-on-dark variant of .btn-secondary, for use over the dark hero/   */
/* mission-strip surfaces where the brand-blue outline reads poorly.     */
.btn-secondary--on-dark {
  color: #fff;
  border-color: #fff;
}
.btn-secondary--on-dark:hover {
  background: #fff;
  color: var(--color-ink);
}

/* ---------------------------------------------------------------------- */
/* Homepage review strip (social proof)                                  */
/* ---------------------------------------------------------------------- */

.review-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
@media (max-width: 900px) {
  .review-strip { grid-template-columns: 1fr; }
}
.review-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  margin: 0;
}
.review-card__quote {
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.65;
  color: var(--color-ink-2);
  margin: 0;
}
.review-card__meta {
  margin-top: auto;
  padding-top: var(--space-1);
  font-size: 13px;
  color: var(--color-ink-3);
}
.review-card__meta a {
  color: var(--color-brand);
  text-decoration: none;
}
.review-card__meta a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------- */
/* Mission strip                                                         */
/* ---------------------------------------------------------------------- */

.mission-strip {
  background: var(--color-dark);
  color: #fff;
  text-align: center;
}
.mission-strip__inner {
  max-width: 700px;
  margin: 0 auto;
}
.mission-strip__body {
  color: rgba(255, 255, 255, 0.8);
  margin-top: var(--space-3);
}
.mission-strip__stat {
  color: rgba(255, 255, 255, 0.6);
  margin-top: var(--space-2);
}

/* ---------------------------------------------------------------------- */
/* Roast tiles ("Browse by roast")                                       */
/* ---------------------------------------------------------------------- */

.roast-tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-md);
  overflow: hidden;
  text-decoration: none;
}
.roast-tile__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.roast-tile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(10, 22, 40, 0.55);
  transition: background 0.15s;
}
.roast-tile:hover::before {
  background: rgba(10, 22, 40, 0.4);
}
.roast-tile__label {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}

/* ---------------------------------------------------------------------- */
/* Loading-spinner utility                                                 */
/* Applied by JS to any element carrying [data-loading-spinner] on click. */
/* ---------------------------------------------------------------------- */

@keyframes cupped-spin {
  to { transform: rotate(360deg); }
}

/* The spinning ring itself — rendered as a ::before pseudo-element so no
   extra markup is needed. Border colour is rgba(255,255,255,0.35) for the
   "track" and white for the leading edge, which reads correctly on the
   burnt-orange .btn-primary background and on any light background. */
.btn--loading {
  pointer-events: none;
  cursor: not-allowed;
  position: relative;
  color: transparent !important;   /* hide label text without reflowing */
  white-space: nowrap;             /* prevent wrapping while text is invisible */
}

.btn--loading::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1em;
  height: 1em;
  border-radius: var(--radius-full);
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: cupped-spin 0.7s linear infinite;
}

/* Screen-reader label injected by JS — visually hidden but announced */
.btn--loading .btn-loading-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------- */
/* Content / legal pages (About, Contact, Privacy, Terms, FAQ, etc.)      */
/* ---------------------------------------------------------------------- */
/* Self-contained typography so these pages read well without the Tailwind
   typography plugin (which the build deliberately omits — see
   tailwind.config.js). Driven by the .content-prose wrapper, so page
   templates can be near-semantic HTML with no per-element utility classes. */

.content-page {
  max-width: 760px;
  margin-inline: auto;
}

.content-page__header {
  margin-bottom: var(--space-4);
}
.content-page__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--color-ink);
}
.content-page__lead {
  margin-top: var(--space-2);
  font-size: 1.125rem;
  color: var(--color-ink-2);
  max-width: 60ch;
}
.content-page__updated {
  margin-top: var(--space-2);
  font-size: 0.875rem;
  color: var(--color-ink-3);
}

.content-prose {
  color: var(--color-ink-2);
  font-size: 1rem;
  line-height: 1.7;
}
.content-prose > * + * {
  margin-top: var(--space-2);
}
.content-prose h2 {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 1.375rem;
  line-height: 1.25;
  color: var(--color-ink);
  margin-top: var(--space-6);
}
.content-prose h3 {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--color-ink);
  margin-top: var(--space-4);
}
.content-prose p,
.content-prose ul,
.content-prose ol {
  text-wrap: pretty;
}
.content-prose ul,
.content-prose ol {
  padding-left: 1.25rem;
}
.content-prose ul { list-style: disc; }
.content-prose ol { list-style: decimal; }
.content-prose li + li {
  margin-top: var(--space-1);
}
.content-prose a {
  color: var(--color-brand);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.content-prose a:hover {
  color: var(--color-brand-dark);
}
.content-prose strong {
  color: var(--color-ink);
  font-weight: 700;
}
.content-prose hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin-block: var(--space-4);
}

/* Definition-style FAQ / contact rows */
.content-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  box-shadow: var(--shadow-card);
}
.content-card + .content-card {
  margin-top: var(--space-2);
}

/* ---------------------------------------------------------------------- */
/* Star-rating input (Leave a review)                                     */
/* CSS-only radio group. DOM order is 5→1 with row-reverse so the         */
/* `~` sibling combinator fills stars to the LEFT of the hovered/checked  */
/* one. Follows the .star-rating/.star-empty display convention: filled    */
/* stars are ink, empty are border-strong — theme-aware via tokens.       */
/* ---------------------------------------------------------------------- */

.star-input {
  display: inline-flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: 2px;
}
/* Visually hidden but still focusable/clickable via the labels. The
   width/height/appearance carry !important to survive base.html's global
   input-sizing override (which is itself !important); the radios also carry
   .field-compact in the template to opt out of that rule entirely — this is
   belt-and-braces so the picker never degrades to visible square boxes. */
.star-input input {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  min-height: 0 !important;
  padding: 0 !important;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  appearance: none;
}
.star-input label {
  font-size: 32px;
  line-height: 1;
  padding: 2px;
  color: var(--color-border-strong);
  cursor: pointer;
  transition: color 0.1s, transform 0.1s;
  border-radius: var(--radius-sm);
}
.star-input label:hover { transform: scale(1.12); }
.star-input label:hover,
.star-input label:hover ~ label,
.star-input input:checked ~ label,
.star-input input:checked + label {
  color: var(--color-ink);
}
.star-input input:focus-visible + label {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

/* ====================================================================== */
/* DARK MODE                                                              */
/*                                                                        */
/* Driven by a `dark` class on <html> (toggled in templates/base.html).   */
/* Two layers:                                                            */
/*   1. Token overrides — anything referencing a --color-* token (header,  */
/*      footer, cards, buttons, badges, .form-input, inline style="" that  */
/*      uses a token) flips automatically.                                 */
/*   2. Tailwind bridge — templates carry hardcoded Tailwind colour        */
/*      utilities that DON'T read tokens; the ones actually in use are      */
/*      remapped here. Selectors are `.dark .util` = specificity (0,2,0),   */
/*      no !important — so a per-element `dark:` variant (also (0,2,0) but   */
/*      later in source order) can override any of these where a specific    */
/*      template needs something different. That's the escape hatch the      */
/*      per-page fixes use.                                                  */
/* ====================================================================== */

.dark {
  /* Surfaces */
  --color-bg: #0f141b;
  --color-surface: #1a2330;
  --color-surface-2: #232f3e;
  --color-dark: #060c16;

  /* Text — inverted ramp */
  --color-ink: #f2efeb;
  --color-ink-2: #b9c2cd;
  --color-ink-3: #7f8b99;

  /* Borders */
  --color-border: #2c3a4a;
  --color-border-strong: #3e4f63;

  /* Semantic feedback, lifted for dark surfaces */
  --color-danger: #f87171;
  --color-danger-strong: #fca5a5;
  --color-danger-border: rgba(220, 38, 38, 0.45);
  --color-danger-bg: rgba(220, 38, 38, 0.12);
  --color-success-strong: #4ade80;
  --color-success-bg: rgba(22, 163, 74, 0.12);

  /* Brand blue brightened for contrast on dark (used as link/active TEXT);
     burnt-orange CTA unchanged. */
  --color-brand: #3ba0e0;
  --color-brand-dark: #2b86c4;
  /* Fill behind white text deepened (white on #3ba0e0 is only 2.9:1; on this
     it is ~8:1). */
  --color-brand-fill: #02517f;

  /* Heavier shadows so cards still register on a dark background */
  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.45), 0 0 1px rgba(0, 0, 0, 0.6);
  --shadow-card-hover: 0 8px 24px rgba(0, 0, 0, 0.6), 0 0 1px rgba(0, 0, 0, 0.7);
  --shadow-panel: 0 4px 16px rgba(0, 0, 0, 0.55);

  /* Hint native UI (scrollbars, date pickers, default controls) to dark */
  color-scheme: dark;
}

/* Body carries `bg-stone-50 text-stone-900` utilities; cover them directly. */
.dark body { background: var(--color-bg); color: var(--color-ink); }

/* Native form controls with no explicit colour utility default to white. */
.dark input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
.dark select,
.dark textarea {
  background-color: var(--color-surface);
  color: var(--color-ink);
  border-color: var(--color-border);
}
.dark input::placeholder,
.dark textarea::placeholder { color: var(--color-ink-3); }

/* --- Bridge: backgrounds --- */
.dark .bg-white     { background-color: var(--color-surface); }
.dark .bg-stone-50  { background-color: var(--color-bg); }
.dark .bg-stone-100 { background-color: var(--color-surface-2); }
.dark .bg-stone-300 { background-color: var(--color-border-strong); }

/* --- Bridge: text ramp --- */
.dark .text-stone-900,
.dark .text-stone-800,
.dark .text-stone-700 { color: var(--color-ink); }
.dark .text-stone-600,
.dark .text-stone-500 { color: var(--color-ink-2); }
.dark .text-stone-400,
.dark .text-stone-300,
.dark .text-stone-200 { color: var(--color-ink-3); }

/* --- Bridge: borders --- */
.dark .border-stone-200,
.dark .border-stone-300,
.dark .border-stone-400 { border-color: var(--color-border); }
.dark .border-stone-500,
.dark .border-stone-900 { border-color: var(--color-border-strong); }

/* divide-* colours the edge between children */
.dark .divide-stone-100 > :not([hidden]) ~ :not([hidden]),
.dark .divide-stone-200 > :not([hidden]) ~ :not([hidden]) { border-color: var(--color-border); }

/* ring + placeholder */
.dark .ring-stone-500 { --tw-ring-color: var(--color-border-strong); }
.dark .placeholder-stone-400::placeholder { color: var(--color-ink-3); }

/* --- Bridge: semantic tints. Near-white 50-level panels glare on dark, so   */
/*     drop them to a muted version of their hue and lift the text/borders.   */
.dark .bg-red-50     { background-color: rgba(220, 38, 38, 0.12); }
.dark .bg-green-50,
.dark .bg-emerald-50 { background-color: rgba(22, 163, 74, 0.12); }
.dark .bg-emerald-100 { background-color: rgba(22, 163, 74, 0.18); }
.dark .bg-amber-50   { background-color: rgba(217, 119, 6, 0.12); }
.dark .border-red-200   { border-color: rgba(220, 38, 38, 0.35); }
.dark .border-green-200 { border-color: rgba(22, 163, 74, 0.35); }
.dark .border-amber-200 { border-color: rgba(217, 119, 6, 0.35); }
.dark .text-red-500,
.dark .text-red-600,
.dark .text-red-700,
.dark .text-red-900    { color: #f87171; }
.dark .text-green-700,
.dark .text-emerald-700 { color: #4ade80; }
.dark .text-amber-800,
.dark .text-amber-900  { color: #fbbf24; }
.dark .text-gray-600   { color: var(--color-ink-2); }

/* Solid action buttons keep hue, settle slightly */
.dark .bg-red-600   { background-color: #dc2626; }
.dark .bg-red-700   { background-color: #b91c1c; }
.dark .bg-green-600 { background-color: #16a34a; }

/* Solid brand-blue bands (arbitrary Tailwind values used on hero/CTA strips).
   The selectors target the literal class names `bg-[#025F9C]` / `bg-[#024C7D]`. */
.dark .bg-\[\#025F9C\] { background-color: var(--color-brand-fill); }
.dark .bg-\[\#024C7D\] { background-color: #01314f; }

/* --- Theme toggle button (header) --- */
.theme-toggle {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-ink-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  border-radius: var(--radius-full);
  transition: background 0.15s, color 0.15s;
}
.theme-toggle:hover { color: var(--color-ink); background: var(--color-surface-2); }
.theme-toggle__sun  { display: none; }
.theme-toggle__moon { display: inline-flex; }
.dark .theme-toggle__moon { display: none; }
.dark .theme-toggle__sun  { display: inline-flex; }
