/* Queensland Government, as premiers.qld.gov.au sets it: brand blue #005eb8,
   the navy it darkens to #05325f, sky #84d3ff for highlights, the Queensland
   yellow #efd700 for the one accent, ink #414141 on white, and light grey
   surfaces #f5f5f5 with #ebebeb hairlines. The department's own logo is the
   coat of arms in #022a50, which the page background picks up. Swap these and
   the app follows. Type is FF Meta Pro for headings (the real brand face, used
   when installed) over Noto Sans, which the site loads from Google Fonts and
   which stands in for both here — loaded in index.html. */
:root {
  --font: "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-head: "ff-meta-pro-bold", "ff-meta-pro", "Noto Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;

  --page: #022a50;
  --brand: #005eb8;
  --brand-deep: #05325f;
  --brand-line: rgba(0, 94, 184, 0.16);
  --bubble: #ffffff;
  --ink: #414141;
  --white-soft: rgba(255, 255, 255, 0.82);
  --live: #005eb8;
  --error: #b3261e;
  --amber: #efd700;
  /* Back arrow, chat, send and call all render at this size. */
  --icon: 22px;

  /* App surfaces */
  --shop-bg: #f5f5f5;
  --card: #ffffff;
  --muted: #61696b;
  --accent: #005eb8;
  --accent-bright: #307edb;
  --red: #b3261e;
  --heart: #005eb8;
  --star: #efd700;
  --hairline: #e0e0e0;
}

* { box-sizing: border-box; }

/* Screens set display, so `hidden` needs to outrank it. */
[hidden] { display: none !important; }

html, body { height: 100%; }

/* Phone sits dead centre of the page, both axes. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--page);
  color: var(--ink);
  font: 15px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
}

/* Two columns: the copy on the left, the phone on the right. Both are
   centred against each other on the cross axis, and the pair is centred in
   the page by the flex rules on body. */
.stage {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(32px, 6vw, 96px);
  width: 100%;
  max-width: 1180px;
}

.intro {
  flex: 1 1 0;
  max-width: 560px;
  /* The logo is pushed to the bottom of the column, so the block needs a
     height to push against — matched to the phone's own height. */
  min-height: min(900px, calc(100vh - 40px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: #fff;
}

.intro h1 {
  margin: 0 0 18px;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(34px, 4.4vw, 52px);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.intro p {
  margin: 0 0 12px;
  color: var(--white-soft);
  font-size: 17px;
}

.intro ol,
.intro ul {
  margin: 0 0 26px;
  padding-left: 22px;
  color: var(--white-soft);
  font-size: 16px;
}

.intro li { margin-bottom: 10px; }
.intro li:last-child { margin-bottom: 0; }
.intro strong { color: #fff; }

/* Sits under the copy, and travels with it as the block centres. Opens the
   Spaceman site in a new tab. Sized 25% up from the original 300px/70%. */
.intro-logo-link {
  display: block;
  padding-top: 44px;
  width: min(375px, 87.5%);
}

.intro-logo {
  display: block;
  width: 100%;
  height: auto;
}

/* Below this the columns can't both breathe, so stack them and let the
   page scroll instead of squeezing the phone. */
@media (max-width: 900px) {
  body { align-items: flex-start; }

  .stage {
    flex-direction: column;
    gap: 40px;
  }

  .intro {
    min-height: 0;
    max-width: min(430px, 100%);
    align-items: flex-start;
  }

  .intro-logo-link { padding-top: 24px; }
}

.phone {
  flex: none;
  width: min(430px, 100%);
  height: min(900px, calc(100vh - 40px));
  padding: 12px;
  border-radius: 52px;
  background: #000;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22), 0 40px 80px rgba(0, 0, 0, 0.6);
}

.app {
  position: relative;
  height: 100%;
  display: grid;
  /* statusbar / header / screen / footer (tabbar, composer or product bar) */
  grid-template-rows: auto auto 1fr auto;
  border-radius: 42px;
  overflow: hidden;
  background: #fff;
}

/* Every screen fills the middle row and scrolls independently. */
.screen {
  overflow-y: auto;
  background: var(--shop-bg);
  scrollbar-width: none;
}
.screen::-webkit-scrollbar { display: none; }
#screen-chat { background: var(--shop-bg); }

/* ---------------------------------------------------------------- statusbar --- */

.statusbar {
  height: 50px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 26px;
  color: var(--ink);
}
.time { font-size: 15px; font-weight: 600; letter-spacing: 0.01em; }

.island {
  width: 106px;
  height: 30px;
  border-radius: 16px;
  background: #000;
}

.indicators {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 6px;
}
.indicators svg { fill: currentColor; height: 12px; }
.indicators .signal { width: 18px; }
.indicators .wifi { width: 16px; }
.indicators .battery { width: 26px; }

/* ------------------------------------------------------------------ header --- */

header {
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  align-items: center;
  gap: 8px;
  padding: 6px 18px 12px;
}

/* Logo slot: drop a file at public/logo.png and it replaces the wordmark. */
.brand {
  display: grid;
  place-items: center;
  text-align: center;
  font-family: var(--font-head);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--brand-deep);
  /* Tapping the wordmark returns to home from anywhere. */
  cursor: pointer;
}
.brand .glass { font-size: 17px; }
/* Whole artwork, letterboxed rather than cropped, so dropping in a different
   logo needs no per-file offsets. --logo-ratio is width/height of the art;
   `contain` keeps it honest if the real file differs. */
.brand-logo {
  /* 34px keeps the logo inside the 36px icon-button row, so the header
     doesn't grow, while filling the middle column properly. */
  --logo-h: 34px;
  --logo-ratio: 3.036;
  height: var(--logo-h);
  width: calc(var(--logo-h) * var(--logo-ratio));
  max-width: 100%;
  background-image: var(--logo-src, url("/logo.png"));
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.brand-logo[hidden] { display: none; }

.icon-btn {
  position: relative;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.icon-btn svg { width: var(--icon); height: var(--icon); fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* Connection state is conveyed by the call button itself: outlined black
   phone when idle, filled black hang-up while live. */

/* --------------------------------------------------------------- transcript --- */

#screen-chat { display: flex; flex-direction: column; overflow: hidden; }

#transcript {
  flex: 1;
  overflow-y: auto;
  padding: 6px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
#transcript::-webkit-scrollbar { width: 6px; }
#transcript::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.18); border-radius: 3px; }

.row {
  display: flex;
  align-items: flex-end;
}
.row.user { justify-content: flex-end; }

.bubble {
  max-width: 88%;
  /* Half the leading of the 1.5 default — the gap between lines, not the glyphs. */
  line-height: 1.25;
  padding: 13px 16px;
  border-radius: 18px;
  background: var(--bubble);
  color: var(--ink);
  border: 1px solid var(--hairline);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.bubble p { margin: 0; }

/* On a light transcript the two speakers separate by colour: the person's own
   turns are the blue ones, the department's are white. */
.row.user .bubble {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

.row.system {
  flex-direction: column;
  align-items: center;
  gap: 2px;
  text-align: center;
  font-size: 12.5px;
  color: var(--muted);
  padding: 2px 20px;
}

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

.card {
  /* Fixed width, not max-width: while the image is still generating the card
     has little content and would otherwise shrink to a narrow column, then
     jump wider when the picture and product strip arrive. */
  width: 92%;
  max-width: 92%;
  padding: 16px;
  border-radius: 20px;
  background: var(--brand-deep);
  color: #fff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.card-head { font-family: var(--font-head); font-size: 19px; font-weight: 700; letter-spacing: 0; }

/* Direct children only: the service tiles in the strip live inside .card too,
   and must not inherit the picture's crop. */
.card > img,
.card > .holder {
  width: 100%;
  /* 5:3 rather than 4:3 — at the same width that is exactly 20% less height. */
  aspect-ratio: 5 / 3;
  border-radius: 14px;
  border: 3px solid #fff;
}
.card > img { display: block; object-fit: cover; }

.card-text { display: flex; flex-direction: column; gap: 3px; }

.card-title {
  margin: 0;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fff;
}
/* Breathing room above a second title, but not above the first. */
.card-title + * { margin-bottom: 4px; }
.card-desc + .card-title,
.ingredients + .card-title { margin-top: 6px; }

.card-desc { margin: 0; font-size: 14px; line-height: 1.22; color: rgba(255, 255, 255, 0.92); }

.ingredients,
.method {
  margin: 0;
  font-size: 14px;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.92);
}
.ingredients { padding: 0; list-style: none; }
.method { padding-left: 18px; }
.method li { padding-left: 2px; }
.method li + li { margin-top: 3px; }

/* Service strip inside a card. Sits within the card's own padding so it insets
   equally on both sides, matching the text above it. */
.card-shop {
  display: flex;
  gap: 10px;
  margin: 6px 0 0;
  padding: 0 0 4px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.card-shop::-webkit-scrollbar { display: none; }
.card-shop .card-product {
  flex: none;
  width: 152px;
  scroll-snap-align: start;
  color: var(--ink);
}
.card-shop .card-body { padding: 10px; }
.card-shop .card-body strong { font-size: 14.5px; }
.card-shop .sub { font-size: 12.5px; }
.card-shop .meta { font-size: 12px; }
.card-shop .heart { width: 28px; height: 28px; top: 8px; right: 8px; }
.card-shop .heart svg { width: 16px; height: 16px; }

.holder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(0, 0, 0, 0.22);
}
.holder small { color: rgba(255, 255, 255, 0.82); max-width: 85%; text-align: center; line-height: 1.4; }
.holder.error { color: rgba(255, 255, 255, 0.82); }

/* While the image generates, the holder fills the same box the finished photo
   will occupy, so nothing shifts when it swaps in. */
.holder.loading {
  position: relative;
  overflow: hidden;
  justify-content: flex-end;
  padding-bottom: 12px;
}

.holder.loading video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Caption sits over the footage, with a scrim so it stays legible against
   whatever frame is showing. */
.holder.loading span {
  position: relative;
  z-index: 1;
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(3px);
}

/* No holding footage for this tool: centre the caption on the panel instead of
   sitting it at the bottom of a video that isn't there. */
.holder.loading.no-clip {
  justify-content: center;
  padding-bottom: 0;
}
.holder.loading.no-clip span { background: none; backdrop-filter: none; }

/* The finished image rises over the still-playing video rather than snapping
   in. Duration is mirrored by FADE_MS in chat.js. */
.holder.swap {
  position: relative;
  overflow: hidden;
  padding: 0;
  /* Card colour, not black: if a frame ever slips through between the video
     and the image, it reads as the card rather than a flash. */
  background: var(--brand-deep);
}

.holder.swap video,
.holder.swap img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 1300ms ease;
}

/* The image starts hidden and is revealed once it has decoded, so the fade
   never rises to a blank frame. */
.holder.swap img { opacity: 0; }
.holder.swap img.shown { opacity: 1; }
.holder.swap video.gone { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .holder.swap video,
  .holder.swap img { transition: none; }
}

/* ----------------------------------------------------------------- composer --- */

#composer {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px 20px;
}

.pill {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  padding: 0 14px;
  border-radius: 26px;
  background: #fff;
  border: 1px solid var(--hairline);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.pill svg { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Sits inside the pill, left of the field, the way the send button sits right
   of it — an upload is an input to the conversation, not a separate action. */
.attach {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--icon);
  height: var(--icon);
  color: var(--ink);
  cursor: pointer;
}
.attach svg {
  width: var(--icon);
  height: var(--icon);
  stroke: currentColor;
  stroke-width: 1.9;
}

#text-input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: transparent;
}
#text-input::placeholder { color: #9a9b9b; }

.send {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--icon);
  height: var(--icon);
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--brand);
  cursor: pointer;
}
.send svg { width: var(--icon); height: var(--icon); stroke: currentColor; }

.call {
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: #fff;
  color: var(--brand);
  cursor: pointer;
  /* Outlined rather than filled, so the live state below can invert it. */
  box-shadow: inset 0 0 0 1.5px var(--brand), 0 1px 3px rgba(0, 0, 0, 0.06);
  transition: background 0.15s, color 0.15s, transform 0.15s;
}
.call svg { width: var(--icon); height: var(--icon); fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.call:hover { transform: scale(1.04); }
/* Live call inverts the button into a filled hang-up. */
.call[data-on="true"] { background: var(--brand); color: #fff; }
.call[data-on="true"] svg { transform: rotate(135deg); }

/* ============================================================== shop screens === */

.section-title {
  margin: 18px 0 12px;
  font-family: var(--font-head);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--brand-deep);
}

.screen { padding: 0 16px 20px; }
.screen-product { padding: 0; }

.empty { margin: 24px 4px; color: var(--muted); font-size: 14px; text-align: center; }

/* ------------------------------------------------------------------- hero --- */

/* A scroll-snap track of the department's event tiles. Each slide is the full
   width of the rail, so a swipe lands on exactly one; app.js auto-advances it
   and keeps the dots in step. */
.hero-slider {
  position: relative;
  margin-top: 14px;
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 16 / 11;
  /* Shows through until the first image paints, so a slow load stays a
     brand-coloured card rather than a white box. */
  background: var(--brand-deep);
}
.hero-track {
  display: flex;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.hero-track::-webkit-scrollbar { display: none; }
.hero-slide {
  position: relative;
  flex: none;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  text-align: left;
  cursor: pointer;
  color: #fff;
  background: var(--brand-deep);
}
.hero-slide img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Scrim only over the lower half, where the caption sits — the tiles carry
   their own artwork and lettering up top. */
.hero-slide::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 45%, rgba(2, 42, 80, 0.82) 100%);
}
.hero-copy { position: absolute; z-index: 2; left: 20px; right: 20px; bottom: 26px; }
.hero-copy h2 { margin: 0 0 3px; font-family: var(--font-head); font-size: 22px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; }
.hero-copy p { margin: 0; font-size: 13.5px; line-height: 1.3; color: rgba(255, 255, 255, 0.92); }

.hero-dots {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 10px;
  display: flex;
  justify-content: center;
  gap: 6px;
}
.hero-dots button {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  cursor: pointer;
  transition: width 0.2s ease, background 0.2s ease;
}
.hero-dots button.on { width: 18px; border-radius: 4px; background: #fff; }

@media (prefers-reduced-motion: reduce) {
  .hero-track { scroll-behavior: auto; }
}

/* --------------------------------------------------------------- products --- */

.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.card-product {
  background: var(--card);
  border-radius: 16px;
  overflow: hidden;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

.card-media { position: relative; }
.card-body { padding: 12px; display: flex; flex-direction: column; gap: 2px; }
.card-body strong { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
.sub { color: var(--muted); font-size: 13px; line-height: 1.25; }
.meta { color: var(--brand); font-size: 12.5px; font-weight: 600; line-height: 1.25; margin-top: 2px; }

/* What sort of thing this is — Event, Guide, Register — in the kind's own
   colour, over the corner of the tile. */
.kind-tag {
  position: absolute;
  left: 10px;
  bottom: 10px;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.row-body .kind-tag { position: static; padding: 0; background: none; font-size: 10.5px; }

.thumb {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: 14px;
}
/* Real imagery fills the tile; the tint behind it goes. */
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.thumb.has-photo { background: #fff !important; padding: 0; }
/* The glyph is a placeholder; a real photo loading next to it wins. */
.thumb img + .pack { display: none; }
.pack { height: 44%; width: auto; }
.thumb.big { aspect-ratio: 4 / 3; border-radius: 18px; }


.heart {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #fff;
  color: var(--heart);
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
/* Outline by default, solid once favourited — same glyph as the tab bar. */
.heart svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.heart.on svg { fill: currentColor; }
.heart.inline { position: static; box-shadow: none; background: transparent; width: 26px; height: 26px; }
.heart.inline svg { width: 24px; height: 24px; }
.heart.floating { top: 16px; right: 16px; }

/* ------------------------------------------------------------ search rows --- */

.search-field {
  width: 100%;
  margin-top: 14px;
  padding: 16px 18px;
  font: inherit;
  font-size: 16px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  outline: none;
}
.search-field::placeholder { color: #9a9b9b; }

.chips { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 16px; }
.chip {
  flex: 1 1 28%;
  padding: 11px 8px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  cursor: pointer;
}
.chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }

.rows { display: flex; flex-direction: column; gap: 10px; }

.row-product {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px 10px 10px;
  background: var(--card);
  border-radius: 14px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.row-product .thumb { width: 62px; aspect-ratio: 1; padding: 7px; border-radius: 10px; flex: none; }
.row-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.row-body strong { font-size: 16.5px; font-weight: 700; letter-spacing: -0.01em; }
.row-body strong { font-size: 15.5px; line-height: 1.25; }
.row-product .heart.inline { flex: none; }

.account-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  background: var(--card);
  border-radius: 16px;
}
.account-card + .account-card { margin-top: 10px; }
.fine-print { margin: 18px 4px 0; color: var(--muted); font-size: 13px; text-align: center; }
.account-card strong { display: block; font-size: 17px; }
.account-card span { color: var(--muted); font-size: 14px; }
.avatar-lg {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--shop-bg);
}
.avatar-lg svg { width: 26px; height: 26px; fill: none; stroke: var(--brand); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* --------------------------------------------------------- service detail --- */

.screen-product { padding: 14px 16px 20px; }
.product-hero { position: relative; }
.product-info { padding: 18px 2px 0; }
.tag {
  display: inline-block;
  padding: 7px 14px;
  border-radius: 999px;
  /* Outlined, not filled: the detail screen sits on the same grey the pill
     used, so a filled chip would disappear against it. */
  background: #fff;
  border: 1px solid var(--hairline);
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.product-info h2 { margin: 14px 0 2px; font-family: var(--font-head); font-size: 26px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; color: var(--brand-deep); }
.product-info .sub { font-size: 15px; }
.product-info .summary { margin: 14px 0 0; font-size: 15.5px; line-height: 1.45; }

/* The facts of a service, two columns: the label and the value. */
.facts { margin: 18px 0 0; padding: 4px 0 0; border-top: 1px solid var(--hairline); }
.facts div { display: grid; grid-template-columns: 96px 1fr; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--hairline); font-size: 14px; }
.facts dt { margin: 0; color: var(--muted); font-weight: 600; }
.facts dd { margin: 0; color: var(--ink); }

.product-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px 20px;
  background: var(--shop-bg);
  border-top: 1px solid var(--hairline);
}
.bar-save {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  flex: none;
  border: 1px solid var(--hairline);
  border-radius: 4px;
  background: var(--card);
  color: var(--brand);
  cursor: pointer;
}
.bar-save svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linejoin: round; }
.bar-save.on svg { fill: currentColor; }
/* The site sets its calls to action as solid blue rectangles, so the pill
   shape is dropped here even though chips keep theirs. */
.add-to-cart {
  flex: 1;
  display: grid;
  place-items: center;
  height: 54px;
  border: 0;
  border-radius: 4px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-family: var(--font-head);
  font-size: 16px;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

/* ----------------------------------------------------------------- tabbar --- */

#tabbar {
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding: 12px 14px 20px;
  background: #fff;
  border-top: 1px solid var(--hairline);
}
#tabbar button {
  position: relative;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border: 0;
  border-radius: 50%;
  background: var(--shop-bg);
  color: var(--ink);
  cursor: pointer;
}
#tabbar svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
#tabbar button.active { background: var(--brand); color: #fff; }

/* ----------------------------------------------------------------- drawer --- */

.drawer-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 5; }

.drawer {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 6;
  width: 78%;
  display: flex;
  flex-direction: column;
  background: #fff;
  transform: translateX(-100%);
  transition: transform 0.22s ease;
}
.drawer.open { transform: translateX(0); }

/* Light, so the navy crest reads; the site never puts the logo on blue. */
.drawer-head { padding: 46px 22px 18px; background: var(--shop-bg); color: var(--ink); border-bottom: 1px solid var(--hairline); }
.drawer-head strong { display: block; font-family: var(--font-head); font-size: 18px; font-weight: 700; letter-spacing: -0.01em; color: var(--brand-deep); }
.drawer-head span { font-size: 14px; color: var(--muted); }
/* Same crop window as the header logo, just smaller. */
.drawer-logo { --logo-h: 38px; margin-bottom: 6px; }

.drawer-links { flex: 1; display: flex; flex-direction: column; padding: 12px 0; }
.drawer-links button {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 15px 22px;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 18px;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.drawer-links svg {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--brand);
}
.drawer-links button:hover { background: var(--shop-bg); }

.drawer-foot { padding: 18px 22px 26px; border-top: 1px solid var(--hairline); }
.drawer-foot strong { display: block; color: var(--heart); font-size: 17px; font-weight: 700; }
.drawer-foot span { font-size: 14px; color: var(--muted); }

/* Home rails: horizontal scrollers that bleed to the screen edges, so a
   partially visible card signals there is more to swipe. Saved keeps the
   two-column .grid. */
.rail {
  display: flex;
  gap: 12px;
  margin: 0 -16px;
  padding: 0 16px 4px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Snap points sit at the padding edge, not the container edge — without this
     the first card snaps flush left and loses the 16px inset. */
  scroll-padding-left: 16px;
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail .card-product {
  flex: none;
  width: 168px;
  scroll-snap-align: start;
}

/* An unordered method list (the event planner's drink types) still wants the
   same indent as the numbered one, just with bullets. */
ul.method { list-style: disc; }
