/* Solstice Studio — theme colours (--primary, --bg, --text, --font) come from the admin;
   everything else here is this design's own. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  line-height: 1.55;
}

img { max-width: 100%; display: block; }

.wrap {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.5rem;
}

a { color: var(--primary); }

.muted { color: #6b7280; }

/* ---- Header ---------------------------------------------------------- */

.siteHeader { border-bottom: 1px solid #e4e6ea; }

.siteHeader__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 1.1rem 1.5rem;
}

.brand { text-decoration: none; }
.brand__mark { font-weight: 700; font-size: 1.15rem; color: var(--text); }

.nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.nav__link { text-decoration: none; color: var(--text); font-weight: 500; }
.nav__link:hover { color: var(--primary); }

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

.btn {
  display: inline-block;
  margin-top: 1.25rem;
  padding: 0.75rem 1.5rem;
  background: var(--primary);
  color: #fff;
  text-decoration: none;
  border-radius: 0.4rem;
  font-weight: 600;
}
.btn--light { background: #fff; color: var(--primary); }

/* ---- Hero --------------------------------------------------------------- */

/* background-size and friends are set here and the image itself is not: the hero carries a
   data-field-bg, so whoever runs the site picks the photo and the design keeps the framing.
   With no photo chosen these rules do nothing at all. */
.hero {
  padding: 5rem 0 4rem;
  text-align: center;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.hero__eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--primary);
  margin: 0 0 0.75rem;
}
.hero__title { font-size: clamp(2rem, 5vw, 3rem); margin: 0 0 1rem; line-height: 1.1; }
.hero__lead { max-width: 40rem; margin: 0 auto; color: #4b5563; font-size: 1.1rem; }

/* ---- Highlights / cards -------------------------------------------------- */

.highlights { padding: 3rem 0; }
.highlights h2, .servicesList h2, .portfolioGrid h2, .team h2 {
  font-size: 1.75rem;
  margin: 0 0 2rem;
  text-align: center;
}

.cardGrid, .serviceGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 2rem;
}

.card, .service {
  padding: 1.5rem;
  border: 1px solid #e4e6ea;
  border-radius: 0.6rem;
}

.card__icon, .service__icon { width: 2.5rem; height: 2.5rem; margin-bottom: 1rem; }
.card h3, .service h3 { margin: 0 0 0.5rem; font-size: 1.1rem; }
.card p, .service p { margin: 0; color: #4b5563; }

/* ---- Prose ---------------------------------------------------------------- */

.prose { padding: 3rem 0; background: #f5f6f8; }
.proseBody { max-width: 42rem; margin: 0 auto; }
.proseBody h2 { margin-top: 0; }
.proseBody ul { padding-left: 1.25rem; }

/* ---- CTA banner ------------------------------------------------------------ */

.cta {
  padding: 4rem 0;
  text-align: center;
  background: var(--primary);
  color: #fff;
}
.cta h2 { margin: 0 0 0.75rem; font-size: 1.75rem; }
.cta p { max-width: 34rem; margin: 0 auto; opacity: 0.9; }

/* ---- Page header (shared across inner pages) ------------------------------ */

.pageHeader { padding: 3.5rem 0 2rem; text-align: center; }
.pageHeader h1 { font-size: clamp(1.75rem, 4vw, 2.5rem); margin: 0; }

/* ---- About ------------------------------------------------------------------ */

.aboutIntro { padding: 1rem 0 3rem; }
.aboutIntro__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
}
@media (min-width: 48rem) {
  .aboutIntro__grid { grid-template-columns: 1fr 1fr; }
}
.aboutIntro__image { border-radius: 0.6rem; }

.team { padding: 1rem 0 4rem; }
.teamGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 2rem;
}
.teamCard { text-align: center; }
.teamCard__photo {
  width: 7rem;
  height: 7rem;
  border-radius: 50%;
  margin: 0 auto 1rem;
}
.teamCard h3 { margin: 0 0 0.15rem; font-size: 1.05rem; }
.teamCard__role { color: var(--primary); font-weight: 600; font-size: 0.9rem; margin: 0 0 0.5rem; }
.teamCard p:not(.teamCard__role) { color: #4b5563; margin: 0; }

/* ---- Services ---------------------------------------------------------------- */

.servicesList { padding: 1rem 0 4rem; }

/* ---- Portfolio ----------------------------------------------------------------- */

.portfolioGrid { padding: 1rem 0 4rem; }
.projectGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 2rem;
}
.project__image { border-radius: 0.5rem; margin-bottom: 0.9rem; aspect-ratio: 4 / 3; object-fit: cover; }
.project h3 { margin: 0 0 0.2rem; font-size: 1.05rem; }
.project__category { color: var(--primary); font-weight: 600; font-size: 0.85rem; margin: 0 0 0.4rem; }
.project p:not(.project__category) { color: #4b5563; margin: 0; }

/* ---- Contact ------------------------------------------------------------------- */

.contactIntro { padding: 1rem 0 1rem; text-align: center; }
.contactIntro p { max-width: 34rem; margin: 0 auto; color: #4b5563; }

.contactFormSection { padding: 1rem 0 4rem; }
.enquiry {
  max-width: 32rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.enquiry label { display: flex; flex-direction: column; gap: 0.35rem; font-weight: 600; font-size: 0.9rem; }
.enquiry input, .enquiry textarea {
  font: inherit;
  padding: 0.6rem 0.75rem;
  border: 1px solid #cbd2d9;
  border-radius: 0.4rem;
}
.enquiry textarea { min-height: 7rem; resize: vertical; }
.enquiry .btn { align-self: flex-start; margin-top: 0.25rem; }

/* ---- Newsletter signup ------------------------------------------------------------
   In the footer, so it appears on every page. The label the engine generates for the
   email field is hidden rather than removed: it is what a screen reader announces, and
   the placeholder is not a substitute for one. */
.signup { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.15rem; }
.signup__row { display: flex; flex-direction: column; gap: 0.35rem; }
.signup__row label { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.85rem; }
.signup__row input {
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 0.4rem;
  background: rgba(255, 255, 255, 0.08);
  color: inherit;
  width: 100%;
  max-width: 18rem;
}
.signup__row input::placeholder { color: inherit; opacity: 0.55; }
.signup .btn { align-self: flex-start; }

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

.siteFooter { border-top: 1px solid #e4e6ea; margin-top: 2rem; }
.siteFooter__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  padding: 3rem 1.5rem 2rem;
}
@media (min-width: 48rem) {
  .siteFooter__inner { grid-template-columns: 2fr 1fr 1fr; }
}
.siteFooter__name { font-weight: 700; margin: 0 0 0.35rem; }
.siteFooter__heading { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 0.75rem; }
.siteFooter__col p { margin: 0 0 0.4rem; }
.socialList { list-style: none; margin: 0; padding: 0; }
.socialList li { margin-bottom: 0.4rem; }
.siteFooter__legal { padding: 1.25rem 1.5rem; border-top: 1px solid #e4e6ea; }
.siteFooter__legal p { margin: 0; font-size: 0.85rem; }

/* ---- The "Website design from $300" landing page --------------------------------------

   Everything here is scoped to .page-website-design, the class site/page.html puts on
   <body> from {{ page.slug }}. Every admin-created page shares that one template, so a
   page-scoped block is the only way one of them gets a look of its own without a second
   template and a second route — and scoping it means the rest of the site cannot be
   changed by accident from in here.

   The colours are deliberately not the admin's --primary/--bg/--text. Those belong to the
   client's brand and are theirs to change on the Settings screen; this page is a piece of
   sales collateral with a fixed identity, and a client trying a new brand colour should not
   silently repaint it.

   The two photographs (site/images/website-design/*.webp) are Unsplash — free to use, no
   attribution required — resized and re-compressed to under 130KB each, since "loads in
   under a second on ordinary mobile data" is a claim this exact page makes. Both are
   design assets, not editable content, which is why they are referenced straight from CSS
   rather than as a data-field: this page has a fixed identity the same way its colours do. */

.page-website-design {
  --ink: #0a0a0c;
  --ink-panel: #141419;
  --ink-line: #2a2a32;
  --gold: #d4af37;
  --gold-lift: #e8cf8a;
  --paper: #ece8df;
  --paper-dim: #9a958a;

  background: var(--ink);
  color: var(--paper);
  overflow-x: clip; /* the hero's glow orbs sit partly off-edge on purpose */
}

.page-website-design a { color: var(--gold); }

/* Header and footer are shared furniture, so they are repainted rather than replaced. */
.page-website-design .siteHeader { background: var(--ink); border-bottom-color: var(--ink-line); }
.page-website-design .brand__mark { color: var(--paper); }
.page-website-design .nav__link { color: var(--paper-dim); }
.page-website-design .nav__link:hover { color: var(--gold); }

.page-website-design .siteFooter,
.page-website-design .siteFooter__legal { border-top-color: var(--ink-line); }
.page-website-design .siteFooter__heading { color: var(--gold); }
.page-website-design .muted { color: var(--paper-dim); }

/* ---- Buttons ---- */
.page-website-design .btn {
  position: relative;
  overflow: hidden;
  background: var(--gold);
  color: #17130a;
  border-radius: 0.3rem;
  padding: 0.9rem 1.9rem;
  letter-spacing: 0.01em;
  transition: background .15s ease, transform .05s ease, box-shadow .2s ease;
}
.page-website-design .btn:hover {
  background: var(--gold-lift);
  box-shadow: 0 0.5rem 1.5rem rgba(212, 175, 55, 0.25);
}
.page-website-design .btn:active { transform: translateY(1px); }
/* A light sweep crossing the button on hover — CSS only, no extra markup or image. */
.page-website-design .btn::after {
  content: '';
  position: absolute;
  top: 0; left: -60%;
  width: 40%; height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: skewX(-20deg);
  transition: left .55s ease;
}
.page-website-design .btn:hover::after { left: 130%; }

/* ---- Hero ---- */
.page-website-design .hero {
  position: relative;
  overflow: hidden; /* clips the glow orbs to this section, so they never paint over the header */
  padding: 8rem 0 6rem;
  /* The photo is detailed and full of its own bright colour, so the darkening has to work
     harder than a vignette over a plain colour would: a near-opaque wash plus an extra
     dark pool centred on where the headline sits, then the gold glow and the photograph
     underneath both. */
  background:
    linear-gradient(180deg, rgba(8, 8, 10, .88) 0%, rgba(8, 8, 10, .93) 55%, var(--ink) 100%),
    radial-gradient(46rem 24rem at 50% 40%, rgba(5, 5, 6, .55), transparent 72%),
    radial-gradient(60rem 26rem at 50% -6rem, rgba(212, 175, 55, .2), transparent 70%),
    url('/images/website-design/hero-code.webp') center 30% / cover no-repeat var(--ink);
  border-bottom: 1px solid var(--ink-line);
}
.page-website-design .hero > .wrap { position: relative; z-index: 1; }

/* Two blurred colour pools that drift slowly — texture and motion with no extra image. */
.page-website-design .hero::before,
.page-website-design .hero::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(3.5rem);
  opacity: .35;
  pointer-events: none;
  animation: goldDrift 14s ease-in-out infinite;
}
.page-website-design .hero::before {
  width: 22rem; height: 22rem;
  background: var(--gold);
  top: -8rem; left: -6rem;
}
.page-website-design .hero::after {
  width: 16rem; height: 16rem;
  background: var(--gold-lift);
  bottom: -6rem; right: -4rem;
  animation-delay: -7s;
}

.page-website-design .hero__eyebrow {
  color: var(--gold);
  letter-spacing: 0.16em;
  font-size: 0.78rem;
  opacity: 0;
  animation: heroRise .7s ease .05s forwards;
}
.page-website-design .hero__title {
  color: #fdfcf9;
  font-size: clamp(2.3rem, 6vw, 4rem);
  letter-spacing: -0.02em;
  max-width: 22ch;
  margin-inline: auto;
  text-shadow: 0 2px 4px rgba(0, 0, 0, .8), 0 8px 30px rgba(0, 0, 0, .6);
  opacity: 0;
  animation: heroRise .7s ease .18s forwards;
}
.page-website-design .hero__lead {
  color: #c9c4b8;
  font-size: 1.15rem;
  max-width: 44rem;
  margin-top: 1.5rem;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .7);
  opacity: 0;
  animation: heroRise .7s ease .32s forwards;
}
.page-website-design .hero .btn {
  opacity: 0;
  animation: heroRise .7s ease .46s forwards;
}

@keyframes heroRise {
  from { opacity: 0; transform: translateY(1.1rem); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes goldDrift {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(2rem, 1.5rem); }
}

/* ---- Scroll reveal ----
   site/js/site.js adds .js-reveal to <body> only once it is actually running, then adds
   .is-visible to each element as it crosses into view. Nothing is ever hidden by CSS
   alone, so a visit with JS blocked or failed keeps the plain, fully visible layout rather
   than losing content to a class that was never going to arrive. */
.page-website-design.js-reveal .card,
.page-website-design.js-reveal .service,
.page-website-design.js-reveal .proseBody,
.page-website-design.js-reveal .cta > .wrap {
  opacity: 0;
  transform: translateY(1.5rem);
  /* border-color and box-shadow are only here so this rule's higher specificity (three
     classes vs. .card's own two) does not silently drop them from the transition list —
     .card's hover state still needs both once the card has revealed. */
  transition: opacity .6s ease, transform .6s ease, border-color .2s ease, box-shadow .2s ease;
}
.page-website-design.js-reveal .card.is-visible,
.page-website-design.js-reveal .service.is-visible,
.page-website-design.js-reveal .proseBody.is-visible,
.page-website-design.js-reveal .cta > .wrap.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.page-website-design .cardGrid .card:nth-child(2) { transition-delay: .08s; }
.page-website-design .cardGrid .card:nth-child(3) { transition-delay: .16s; }
.page-website-design .cardGrid .card:nth-child(4) { transition-delay: .24s; }
.page-website-design .serviceGrid .service:nth-child(2) { transition-delay: .08s; }
.page-website-design .serviceGrid .service:nth-child(3) { transition-delay: .16s; }

/* ---- What the price covers ---- */
.page-website-design .highlights { padding: 5rem 0 1rem; }
.page-website-design .highlights h2,
.page-website-design .servicesList h2 {
  font-size: clamp(1.6rem, 3.5vw, 2.1rem);
  letter-spacing: -0.01em;
  margin-bottom: 2.75rem;
}
.page-website-design .card,
.page-website-design .service {
  background: var(--ink-panel);
  border: 1px solid var(--ink-line);
  border-radius: 0.5rem;
  padding: 1.8rem;
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease, opacity .6s ease;
}
.page-website-design .card:hover,
.page-website-design .service:hover {
  border-color: var(--gold);
  transform: translateY(-0.3rem);
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, .35);
}
.page-website-design .card h3 { font-size: 1.15rem; color: var(--paper); }
.page-website-design .card p,
.page-website-design .service p { color: var(--paper-dim); }

/* ---- How the two weeks work ---- */
.page-website-design .prose {
  position: relative;
  overflow: hidden;
  padding: 5rem 0;
  margin-top: 4rem;
  /* The photo lives on the right and fades under the panel colour toward the text, so the
     list stays fully readable on the left without a flat overlay hiding the image outright. */
  background:
    linear-gradient(90deg, var(--ink-panel) 38%, rgba(20, 20, 25, .72) 68%, rgba(20, 20, 25, .35) 100%),
    url('/images/website-design/approach-workspace.webp') right center / cover no-repeat var(--ink-panel);
}
.page-website-design .proseBody { position: relative; max-width: 34rem; }
.page-website-design .proseBody h2 { font-size: 1.9rem; letter-spacing: -0.01em; margin-bottom: 1.25rem; }
.page-website-design .proseBody p { color: var(--paper-dim); }
.page-website-design .proseBody strong { color: var(--gold); font-weight: 600; }
.page-website-design .proseBody ul { list-style: none; padding-left: 0; }
.page-website-design .proseBody li {
  border-left: 2px solid var(--ink-line);
  padding: 0.2rem 0 0.9rem 1.25rem;
  color: var(--paper-dim);
  transition: border-color .2s ease;
}
.page-website-design .proseBody li:hover { border-color: var(--gold); }
.page-website-design .proseBody li:last-child { padding-bottom: 0.2rem; }

/* ---- The three prices ---- */
.page-website-design .servicesList { padding: 5rem 0; }
.page-website-design .service h3 {
  font-size: 1.3rem;
  color: var(--gold);
  letter-spacing: -0.01em;
  padding-bottom: 0.9rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--ink-line);
}

/* ---- Closing band ---- */
.page-website-design .cta {
  background: linear-gradient(120deg, var(--gold) 0%, var(--gold-lift) 100%);
  color: #17130a;
  padding: 5rem 0;
}
.page-website-design .cta h2 { font-size: clamp(1.7rem, 4vw, 2.3rem); letter-spacing: -0.01em; }
.page-website-design .cta p { color: #3a3016; opacity: 1; }
.page-website-design .cta .btn {
  background: #17130a;
  color: var(--gold);
}
.page-website-design .cta .btn:hover { background: #000; }
.page-website-design .cta .btn::after { background: linear-gradient(120deg, transparent, rgba(212, 175, 55, .5), transparent); }

@media (max-width: 40rem) {
  .page-website-design .hero { padding: 5rem 0 4rem; background-position: center 20%; }
  .page-website-design .highlights,
  .page-website-design .servicesList { padding: 3.5rem 0; }
  /* The side-reveal only reads on a wide section; under it the photo becomes a plain,
     darkened top band so the text below is never fighting it for contrast. */
  .page-website-design .prose {
    background:
      linear-gradient(180deg, rgba(10, 10, 12, .55), var(--ink-panel) 65%),
      url('/images/website-design/approach-workspace.webp') center 30% / cover no-repeat var(--ink-panel);
  }
  .page-website-design .proseBody { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .page-website-design .hero::before,
  .page-website-design .hero::after { animation: none; }
  .page-website-design .hero__eyebrow,
  .page-website-design .hero__title,
  .page-website-design .hero__lead,
  .page-website-design .hero .btn {
    opacity: 1;
    animation: none;
  }
  .page-website-design.js-reveal .card,
  .page-website-design.js-reveal .service,
  .page-website-design.js-reveal .proseBody,
  .page-website-design.js-reveal .cta > .wrap {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .page-website-design .btn::after { display: none; }
}


/* ---- The shop ----------------------------------------------------------------------

   Lifted from this engine's previous version, whose design shipped a working storefront,
   and left on its own class names so the markup in site/shop.html, product-detail.html,
   cart.html, checkout.html and order-confirmation.html is the same markup that was already
   proven against site/js/cart.js and site/js/checkout.js.

   Several of these rules style markup that appears in no template at all: cart.js writes
   the whole basket — its lines, quantity steppers, coupon form and totals — into
   [data-cart] itself, and checkout.js writes the payment method radios into
   [data-pay-methods]. Deleting a rule here because "nothing uses it" is how those two
   screens lose their styling with nothing in the templates to explain why.

   The three tokens below are the ones those rules expect and this design did not have.
   --primary, --bg and --text already arrive from the admin's theme settings. */

:root {
  --muted: #6b7280;
  --border: #e4e6ea;
  --surface: #f7f8fa;
  --radius: 8px;
}
.wrap { width: min(var(--wrap), 100% - 2.5rem); margin-inline: auto; }
.muted { color: var(--muted); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* ---------- Header ---------- */

.siteHeader {
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
}
.siteHeader__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 4rem;
}
.brand { text-decoration: none; color: inherit; }
.brand__mark { font-weight: 700; font-size: 1.0625rem; letter-spacing: -.01em; }
.nav { display: flex; gap: .35rem; }
.nav__link {
  padding: .4rem .75rem; border-radius: 7px; text-decoration: none;
  color: var(--text); font-size: .95rem;
}
.nav__link:hover { background: var(--surface); }
.nav__link.is-active { color: var(--primary); font-weight: 600; }
/* ---------- Sections ---------- */

.section { padding-block: var(--gap); }
.section__title { font-size: clamp(1.5rem, 3vw, 2rem); letter-spacing: -.02em; line-height: 1.2; }
.cta--accent .btn--primary { background: #fff; color: var(--primary); }
/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .7rem 1.4rem; border-radius: 8px; border: 1px solid transparent;
  font: inherit; font-size: .95rem; font-weight: 600; text-decoration: none;
  cursor: pointer; transition: opacity .15s, background .15s;
}
.btn--primary { background: var(--primary); color: #fff; }
.btn--primary:hover { opacity: .88; }
.btn--ghost { border-color: var(--border); color: var(--text); background: none; }
.btn--ghost:hover { background: var(--surface); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
/* ---------- Form fields ----------
   Used by the shop's own forms (checkout, the variant picker, the coupon box) — the
   contact form below has its own generated .formField__input, styled the same way, because
   its markup comes from a different code path (lib/routes/public.js) than these static
   templates. Two class names, one look. */

.field { display: block; margin-bottom: 1rem; }
.field__label { display: block; font-size: .9rem; font-weight: 600; margin-bottom: .35rem; }
.input, .select {
  width: 100%; font: inherit; font-size: 1rem; color: var(--text);
  padding: .65rem .8rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg);
}
.input:focus, .select:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
}
textarea.input { resize: vertical; min-height: 5rem; }
/* Long-form text from the rich-text editor. The tag list here mirrors the sanitizer's
   allowlist in lib/render/context.js — anything outside it never reaches the page. */
.prose > * + * { margin-top: 1.15rem; }
.prose h2 { font-size: 1.5rem; letter-spacing: -.02em; margin-top: 2.25rem; }
.prose h3 { font-size: 1.2rem; margin-top: 1.85rem; }
.prose ul, .prose ol { padding-left: 1.35rem; }
.prose li + li { margin-top: .4rem; }
.prose blockquote {
  border-left: 3px solid var(--primary); padding-left: 1.1rem; color: var(--muted);
}
.prose pre {
  background: var(--surface); padding: 1rem; border-radius: 8px;
  overflow-x: auto; font-size: .9rem;
}
.prose code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9em; }
.prose img { border-radius: 8px; }
.prose hr { border: 0; border-top: 1px solid var(--border); margin-block: 2rem; }
.contactForm__status.is-error { background: #fdeceb; color: #b42318; }
/* ---------- Footer ---------- */

.siteFooter { border-top: 1px solid var(--border); margin-top: var(--gap); }
.siteFooter__inner {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 2rem; padding-block: 3rem 2rem;
}
.siteFooter__name { font-weight: 700; }
.siteFooter__heading {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--muted); margin-bottom: .6rem; font-weight: 650;
}
.siteFooter__col p { font-size: .95rem; }
.socialList { list-style: none; font-size: .95rem; }
.socialList li + li { margin-top: .3rem; }
.siteFooter__legal { padding-bottom: 2.5rem; font-size: .88rem; }
/* ---------- Shop ---------- */

.nav__cart { position: relative; font-weight: 650; }
.nav__badge {
  display: inline-grid; place-items: center;
  min-width: 1.35rem; height: 1.35rem; padding: 0 .35rem;
  border-radius: 1rem; background: var(--primary); color: #fff;
  font-size: .75rem; font-weight: 700; line-height: 1;
}
.cartMessage {
  position: fixed; inset: auto 1rem 1rem auto; z-index: 40;
  padding: .7rem 1.1rem; border-radius: .6rem;
  background: #14532d; color: #fff; font-size: .92rem;
  box-shadow: 0 10px 30px rgb(0 0 0 / .18);
}
.cartMessage.is-error { background: #7f1d1d; }
.productGrid {
  display: grid; gap: 1.75rem;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.productCard { transition: transform .15s ease; }
.productCard:hover { transform: translateY(-3px); }
.productCard__media { display: block; }
.productCard__media img,
.productCard__placeholder {
  display: block; width: 100%; aspect-ratio: 4 / 5;
  object-fit: cover; border-radius: .8rem; background: var(--border);
  box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 8px 20px -12px rgb(0 0 0 / .18);
  transition: box-shadow .15s ease;
}
.productCard:hover .productCard__media img { box-shadow: 0 4px 10px rgb(0 0 0 / .06), 0 16px 28px -12px rgb(0 0 0 / .22); }
.productCard__title { font-size: 1.05rem; margin: .85rem 0 .3rem; }
.productCard__title a { text-decoration: none; color: inherit; }
.productCard__title a:hover { color: var(--primary); }
.productCard__excerpt { font-size: .92rem; color: var(--muted); margin-top: .35rem; }
.price { font-weight: 700; }
.price--was { color: var(--muted); font-weight: 500; margin-left: .5rem; text-decoration: line-through; }
.product__layout { display: grid; gap: 3rem; grid-template-columns: 1fr 1fr; align-items: start; }
.product__media {
  border-radius: 1rem; overflow: hidden; background: var(--surface);
  box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 16px 32px -18px rgb(0 0 0 / .22);
}
.product__media img { width: 100%; display: block; }
.product__gallery { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .75rem; }
.product__galleryThumb {
  width: 4.5rem; height: 4.5rem; padding: 0; border-radius: .6rem; overflow: hidden;
  border: 2px solid transparent; background: var(--surface); cursor: pointer; flex: none;
}
.product__galleryThumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.product__galleryThumb.is-active { border-color: var(--primary); }
.product__tag {
  display: inline-block; font-size: .72rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--primary); margin-bottom: .5rem;
}
.product__title { font-size: clamp(1.6rem, 3vw, 2.3rem); letter-spacing: -.02em; margin-bottom: .6rem; }
.product__price { font-size: 1.5rem; margin-bottom: 1.1rem; }
.product__lede { color: var(--muted); margin-bottom: 1.5rem; max-width: 32rem; }
.product__options { margin-bottom: 1.5rem; max-width: 22rem; }
.product__buy { display: flex; gap: .85rem; align-items: center; }
.product__stock { min-height: 1.4rem; margin-top: .9rem; font-size: .88rem; }
.product__sku { margin-top: 1rem; font-size: .85rem; color: var(--muted); }
.product__body { margin-top: 3.5rem; }
.product__foot { margin-top: 2.5rem; }
/* In-stock / low-stock / out-of-stock note, styled as a small pill rather than plain text
   so the state reads at a glance next to the Add button. */
.stockBadge {
  display: inline-flex; align-items: center; gap: .35rem;
  font-weight: 600; font-size: .82rem; padding: .25rem .65rem; border-radius: 1rem;
}
.stockBadge::before { content: ''; width: .4rem; height: .4rem; border-radius: 50%; background: currentColor; }
.stockBadge--in { color: #05683c; background: #e6f5ee; }
.stockBadge--low { color: #92400e; background: #fef3c7; }
.stockBadge--out { color: #b42318; background: #fdeceb; }
/* Quantity input as a stepper: a big tap target either side of the number, rather than a
   bare <input type=number> whose native spinners are tiny and inconsistent across browsers. */
.qtyStepper {
  display: inline-flex; align-items: stretch; height: 2.75rem;
  border: 1px solid var(--border); border-radius: 8px; overflow: hidden;
}
.qtyStepper__btn {
  display: grid; place-items: center; width: 2.5rem; border: 0; background: var(--surface);
  color: var(--text); font-size: 1.1rem; line-height: 1; cursor: pointer;
}
.qtyStepper__btn:hover { background: var(--border); }
.qtyStepper__btn:disabled { opacity: .4; cursor: not-allowed; }
.qtyStepper__input {
  width: 3rem; border: 0; border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  text-align: center; font: inherit; font-weight: 600; -moz-appearance: textfield;
}
.qtyStepper__input::-webkit-outer-spin-button,
.qtyStepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* The basket, checkout and order confirmation are styled by css/shop.css — the same file
   "npm run scan" gives a design with no shop — so the demo shows what a client site gets. */

/* ---- The blog ------------------------------------------------------------------------
   Same pattern as the productGrid/productCard pair above: a listing grid on blog.html,
   a single article on post-detail.html. Kept on its own class names rather than reusing
   .productCard so a site with both a shop and a journal can style them differently. */
.postGrid {
  display: grid; gap: 1.75rem;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}
.postCard { transition: transform .15s ease; }

/* ---- The pager ----
   Shared by any listing that opts into paging with {{#each … paginate=true}}. Class names
   rather than element selectors, so a design can restyle it without fighting specificity. */
.pager {
  display: flex; align-items: center; justify-content: center;
  gap: 1rem; margin-top: 3rem; flex-wrap: wrap;
}
.pager__list {
  display: flex; align-items: center; gap: .35rem;
  list-style: none; margin: 0; padding: 0;
}
.pager__item { display: flex; align-items: center; gap: .35rem; }
.pager__page,
.pager__step {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.25rem; height: 2.25rem; padding: 0 .65rem;
  border: 1px solid var(--border); border-radius: .5rem;
  font-size: .9rem; text-decoration: none; color: inherit;
}
.pager__page:hover,
.pager__step:hover { border-color: var(--primary); }
.pager__page.is-current {
  background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600;
}
.pager__gap { padding: 0 .15rem; opacity: .6; }
.postCard:hover { transform: translateY(-3px); }
.postCard__media { display: block; }
.postCard__media img,
.postCard__placeholder {
  display: block; width: 100%; aspect-ratio: 16 / 10;
  object-fit: cover; border-radius: .8rem; background: var(--border);
  box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 8px 20px -12px rgb(0 0 0 / .18);
  transition: box-shadow .15s ease;
}
.postCard:hover .postCard__media img { box-shadow: 0 4px 10px rgb(0 0 0 / .06), 0 16px 28px -12px rgb(0 0 0 / .22); }
.postCard__date { display: block; font-size: .82rem; color: var(--muted); margin-top: 1rem; }
.postCard__title { font-size: 1.15rem; margin: .35rem 0 .3rem; }
.postCard__title a { text-decoration: none; color: inherit; }
.postCard__title a:hover { color: var(--primary); }
.postCard__excerpt { font-size: .92rem; color: var(--muted); margin-top: .35rem; }

.post__header { max-width: 42rem; margin: 0 auto; padding-top: 2.5rem; text-align: center; }
.post__tag {
  display: inline-block; font-size: .72rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--primary); margin-bottom: .5rem;
}
.post__title { font-size: clamp(1.8rem, 4vw, 2.6rem); letter-spacing: -.02em; margin-bottom: .75rem; }
.post__meta { color: var(--muted); font-size: .92rem; }
.post__meta .post__author::after { content: '·'; margin: 0 .5rem; }
.post__coverWrap { margin-top: 2rem; }
.post__cover {
  width: 100%; max-height: 26rem; object-fit: cover; border-radius: 1rem;
  box-shadow: 0 1px 2px rgb(0 0 0 / .04), 0 16px 32px -18px rgb(0 0 0 / .22);
}
.post__body { margin-top: 2.5rem; }
.post__foot { margin-top: 2.5rem; padding-bottom: 3rem; }

@media (max-width: 680px) {
  .nav {
    display: none; position: absolute; inset: 4rem 0 auto;
    flex-direction: column; padding: .5rem 1.25rem 1rem;
    background: var(--bg); border-bottom: 1px solid var(--border);
  }
  .nav.is-open { display: flex; }
  .nav__link { padding: .6rem .5rem; }
}
