/* ============================================================
   Caterati — Global Stylesheet
   Design System (PRD §4), following the Caterati Brand Guidelines
   ============================================================ */

/* Work Sans is the brand's body face. Imported here rather than linked from
   each page so there is one place to change it — at the cost of an extra
   round trip before first paint. Self-hosting these weights would be faster
   and would drop the third-party request; see the note in README.

   All four weights the style guide uses are loaded: 300 for large intro
   paragraphs, 400 body, 500 labels and buttons, 600 prices and emphasis.
   Before this only 400 and 500 arrived, so every 600 and 700 in the sheet
   was a browser-synthesised smear of the 500 rather than a real weight. */
@import url("https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap");

:root {
  /* ---- Brand palette — Caterati Brand Guidelines, "Colour" ---- */
  --teal: #004851;          /* Estate Teal     PMS 316-C      signature colour */
  --cypress: #072831;       /* Deep Cypress    PMS 546-C      logo, headings, dark grounds */
  --soft-white: #fdfcfa;    /* Soft White                     page background */
  --ink: #101820;           /* Midnight Ink    PMS Black 6-C  body copy */
  --ruby: #710014;          /* Dark Ruby       PMS 484-C      sparing accent */
  --bronze: #212322;        /* Foundry Bronze  PMS 419-C      secondary text, rules */

  /* Tints of the above. The guidelines allow these: "Tints and tonal
     variations are acceptable, provided they remain true to the original
     hue and preserve the overall look and feel." */
  --teal-soft: #0a5f6c;     /* lifted Estate Teal — hovers, active rules */
  --teal-pale: #d5e0e0;     /* Estate Teal at a whisper — panels on ivory */
  /* One step down from Soft White, for alternating panels, card grounds and
     rules. Derived with the same ratio the brand used between Ivory Mist and
     its own second tint, so the two whites step apart by exactly as much. */
  --soft-white-2: #f4f1ed;  /* Soft White, one step down — alternating panels */
  --muted: #5b6360;         /* Foundry Bronze lightened — secondary text */
  --line: #d9d5cc;          /* Foundry Bronze at rule strength */
  --white: #ffffff;

  /* Legacy names kept as aliases so the whole stylesheet did not have to be
     rewritten in one go. Gold split in two: it was the accent on light
     grounds (now Estate Teal) and on dark ones (now Soft White).
     --ivory and --ivory-2 are the page white and its second tint under their
     former names: nine stylesheets and the SVG generators read them, so they
     are pointed at Soft White rather than renamed across all of it. */
  --ivory: var(--soft-white);
  --ivory-2: var(--soft-white-2);
  --navy: var(--teal);
  --navy-deep: var(--cypress);
  --navy-soft: var(--teal-soft);
  --gold: var(--teal);
  --gold-soft: var(--teal-soft);
  --yellow: var(--ivory);
  --cream: var(--ivory);
  --cream-2: var(--ivory-2);

  /* ---- Typography — Website Style Guide §02 ----
     Georgia sets everything that names or announces; Work Sans everything
     that explains. There is no third role: reaching for one means the
     hierarchy is the problem.

     Georgia is REGULAR ONLY. Its bold is heavy and reads commercial, so
     nothing in the site sets --display above 400 — the headings, the
     wordmark and the product names all changed for this. */
  --display: Georgia, "Times New Roman", serif;
  --body: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --track-display: -0.015em; /* display 64px only        -1.5% */
  --track-head: -0.01em;     /* h1 only; h2-h4 are untracked */
  --track-body: -0.01em;     /* body copy          0 to -1.5% */
  --track-support: 0.14em;   /* eyebrows, labels, buttons     */

  /* Type scale — a 1.25 ratio from a 16px base. Every size on the site is one
     of these tokens; nothing between them is legal, because in-between sizes
     are what make two pages stop matching. The mobile step-down is at the
     foot of this file: body sizes hold, only the display sizes come down. */
  --fs-display: 64px;    /* hero statements. One per page.       */
  --fs-h1: 48px;         /* page titles, collection names        */
  --fs-h2: 36px;         /* section headings                     */
  --fs-h3: 28px;         /* sub-sections, card titles, products  */
  --fs-h4: 22px;         /* smallest heading; below this, eyebrow */
  --fs-lead: 20px;       /* first paragraph. Max 3 lines.        */
  --fs-body: 16px;       /* the default. Measure 60-75 chars.    */
  --fs-body-sm: 15px;    /* card copy, sidebars, help text       */
  --fs-price: 18px;      /* prices and totals — Work Sans 600    */
  --fs-label: 13px;      /* eyebrows and button labels           */
  --fs-caption: 12px;    /* credits, legal, metadata. The floor. */

  /* Spacing — a 4px base, used in 8px steps. Generous space is the cheapest
     signal of quality the system has: where a layout feels wrong the fix is
     almost always more space, not more design. */
  --space-1: 4px;    /* icon-to-label, tight inline pairs         */
  --space-2: 8px;    /* label to input, eyebrow to heading        */
  --space-3: 12px;   /* between buttons, chips, tags              */
  --space-4: 16px;   /* paragraph rhythm, small card padding      */
  --space-5: 24px;   /* card padding, grid gutters, form fields   */
  --space-6: 32px;   /* large card padding, heading to body block */
  --space-7: 48px;   /* sub-section separation                    */
  --space-8: 64px;   /* page side margin, band padding            */
  --space-9: 96px;   /* section top/bottom — the default rhythm   */
  --space-10: 128px; /* editorial and hero breathing room only    */

  /* Starting value only. Since CR-02 the bar is two rows tall — one in compact
     mode — so js/main.js measures it and overwrites this on :root. Everything
     that offsets against the bar reads the variable rather than a constant. */
  --nav-h: 138px;
  /* 12 columns, 24px gutters, 64px side margins. --page-pad steps down at the
     breakpoints at the foot of this file (40px tablet, 20px phone) and is the
     one place any full-width band reads its side margin from, so the nav, the
     footer and a hero all sit on the same margin without being told twice. */
  --maxw: 1120px;
  --gutter: 24px;
  --page-pad: 64px;
  /* Squared, everywhere: it reads as jewellery-case rather than app. The guide
     allows two exceptions — radio controls and toggles — and those keep their
     own 50% / 999px rather than reading this token. */
  --radius: 0;
  --radius-control: 999px;
  /* Nothing heavier than 10% black, so this is only ever a hover or an
     overlay. Note that since the page white moved to Soft White #fdfcfa a
     white card is within ~1% of its ground rather than the 4% Ivory Mist gave
     it: what separates a card now is its hairline border, not its fill. */
  --shadow: 0 10px 40px rgba(7, 43, 49, 0.10);      /* cast in Deep Cypress */
  --shadow-lg: 0 24px 70px rgba(7, 43, 49, 0.10);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--body);
  color: var(--ink);
  background: var(--cream);
  line-height: 1.6;
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
}

/* Georgia at 400 — never 700. Each level carries its own size, leading and
   tracking from the scale rather than one --track-head applied to all of
   them: only the display and h1 are tracked in, and h2 down are set solid. */
h1, h2, h3, h4, .display {
  font-family: var(--display);
  font-weight: 400;
  /* Deep Cypress. --navy is the legacy alias for Estate Teal and is still what
     buttons, chips and chat bubbles use, so it is NOT repointed — only the
     logo and the headings move. */
  color: var(--cypress);
  margin: 0 0 0.5em;
}
.display { font-size: var(--fs-display); line-height: 1.05; letter-spacing: var(--track-display); }
h1 { font-size: var(--fs-h1); line-height: 1.1;  letter-spacing: var(--track-head); }
h2 { font-size: var(--fs-h2); line-height: 1.2;  letter-spacing: 0; }
h3 { font-size: var(--fs-h3); line-height: 1.25; letter-spacing: 0; }
h4 { font-size: var(--fs-h4); line-height: 1.35; letter-spacing: 0; }

a { color: var(--gold); text-decoration: none; }
a:hover { text-decoration: underline; }

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

/* Lead paragraph — the first paragraph of a section or a product story. Work
   Sans 300, and the one place that weight is used. .lede is the name the
   markup already uses for it. */
.lead, .lede {
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.55;
}
/* Image credits, legal, metadata, table footnotes. 12px is the floor — no web
   text on the site is set below it. */
.caption { font-size: var(--fs-caption); line-height: 1.5; }

.container {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--page-pad);
}

/* An eyebrow and the heading under it are one unit, which is what the 8px
   gap says — the next thing down is 32px or more away. */
.eyebrow {
  font-family: var(--body);
  text-transform: uppercase;
  letter-spacing: var(--track-support);   /* support copy: 14% */
  font-size: var(--fs-label);
  font-weight: 500;
  color: var(--gold);
  margin-bottom: var(--space-2);
}

/* One focus ring for the whole site. Kept visible rather than styled away: a
   meaningful share of people navigate the checkout by keyboard, and an
   invisible ring makes it unusable for them. Elements sitting on a dark
   ground — the hero controls, a portrait on the villa wall — override this
   with their own, since Estate Teal disappears against a photograph. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
textarea:focus-visible,
input:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}

/* Medium is the default: 48px tall, from 15px of padding over a 13px label.
   Labels are uppercase at 14% tracking, which eats width fast — keep them to
   about four words. The lift the button used to take on hover is gone; on a
   squared, still system it read as the one restless thing on the page. */
.btn {
  display: inline-block;
  font-family: var(--body);
  font-weight: 500;
  font-size: var(--fs-label);
  line-height: 1.2;
  letter-spacing: var(--track-support);
  text-transform: uppercase;
  padding: 15px 32px;
  border: 1px solid var(--navy);
  background: var(--navy);
  color: var(--white);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
  text-align: center;
}
.btn:hover { background: var(--navy-deep); border-color: var(--navy-deep); text-decoration: none; }
/* The other two sizes on the scale: 40px and 56px. */
.btn--sm { font-size: var(--fs-caption); padding: 11px 20px; }
.btn--lg { font-size: 14px; padding: 19px 40px; }
/* The primary call to action. The guidelines put primary buttons in Estate
   Teal, so this and .btn now share a fill and differ only in hover; the
   quieter tier is .btn--ghost. Kept as its own class because the markup
   uses it in fifteen places. */
.btn--gold { background: var(--teal); border-color: var(--teal); color: var(--white); }
.btn--gold:hover { background: var(--teal-soft); border-color: var(--teal-soft); }
/* Dark Ruby is reserved: "use sparingly for promotions, key messages,
   limited editions". Available for those, deliberately not the default. */
.btn--ruby { background: var(--ruby); border-color: var(--ruby); color: var(--white); }
.btn--ruby:hover { background: #8a0018; border-color: #8a0018; }
/* Primary on a dark ground — Deep Cypress, or a photograph laid over it.
   Estate Teal on Deep Cypress measures 1.6:1 and simply disappears, which is
   why the guide inverts the pair there: the button takes the page white and
   the label takes the dark. */
.btn--light { background: var(--soft-white); border-color: var(--soft-white); color: var(--cypress); }
.btn--light:hover { background: var(--white); border-color: var(--white); color: var(--cypress); }
.btn--ghost { background: transparent; color: var(--navy); }
.btn--ghost:hover { background: var(--navy); color: var(--white); }
.btn--block { display: block; width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }

/* ============================================================
   Form controls (Style Guide §04 — Forms & inputs)
   ============================================================ */
/* Square corners and 16px text on every field on the site. The size is not
   cosmetic: iOS zooms the page whenever a focused field is set below 16px,
   which on a checkout reads as the layout jumping the moment you type.
   Colour, ground and border are left to each field's own rule — this only
   sets the shape and the face. Checkboxes and radios are excluded by listing
   the text-ish types explicitly; they keep their native control. */
input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="search"], input[type="password"], input[type="url"], input[type="date"],
select, textarea {
  font-family: var(--body);
  font-size: var(--fs-body);
  border-radius: var(--radius);
}
/* Labels are always visible — never a placeholder standing in for one, which
   disappears the moment someone types, exactly when it is needed.

   The child combinator is load-bearing: a .field can hold a .checkbox-list,
   whose options are labels too, and those are sentence-case phrases that must
   not be uppercased and tracked out. Only the field's OWN label is a label in
   the style-guide sense. */
.field > label, .form-label {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* The "(select all that apply)" aside inside a label would otherwise inherit
   the uppercase and the tracking from it. */
.field > label .form-note {
  text-transform: none;
  letter-spacing: var(--track-body);
  font-weight: 400;
}

/* ============================================================
   Navigation (PRD §2.1)
   ============================================================ */
/* CR-02 (Batch 2) — an ivory bar on the Cartier plan: wordmark centred on the
   page, sections on a second centred line, Cart pinned right. The bar is no
   longer a fixed height — it is two rows tall, or one in compact mode — so
   js/main.js measures it and publishes the result as --nav-h for the sticky
   offsets and the Customs full-bleed calc that need it. */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ivory);
  padding: 15px 0 9px;
  border-bottom: 1px solid var(--line);
  /* One size for every label on the bar — the section tabs and Cart alike, so
     the two can't drift apart when either is retuned. */
  /* 18px. The bar was halved from 1.35rem and then taken back up by half
     again, so it settles at three quarters of where it started. */
  --nav-tab-size: 1.125rem;
}
.nav-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--page-pad);
}
/* Explicit columns, not auto-placement: the hamburger is display:none on wide
   screens, and an auto-placed grid would pull the wordmark into its empty
   column and knock it off the page's centreline. */
.nav-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
}
.brand {
  grid-column: 2;
  justify-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  /* Deep Cypress, not Estate Teal: the wordmark and the headings carry the
     darker of the two brand greens, and the teal is left to the things you can
     act on — buttons, links, the active tab's rule. */
  color: var(--cypress);
  text-align: center;
}
.brand-name {
  font-family: var(--display);
  font-weight: 400;
  /* 3.375rem is the size asked for — a quarter down from 4.5rem — and it holds
     on any bar wide enough for it. Below about 1030px the wordmark would be
     wider than the space left between the hamburger and the cart, so it tracks
     the viewport down instead of pushing the bar into a sideways scroll. All
     three terms carry the same quarter reduction, so the wordmark is 25%
     smaller at every width, not just where the cap applies. */
  font-size: clamp(0.84375rem, 3.9375vw, 2.53125rem);
  line-height: 1.05;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* Set as the brand sets it on the business card and campaign art: support
   copy in Work Sans Medium, uppercase, tracked within the 8-16% range. */
.brand-tagline {
  font-family: var(--body);
  font-size: 0.6rem;
  font-weight: 500;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: var(--track-support);
  color: var(--muted);
  white-space: nowrap;   /* the tagline must never wrap */
}
.brand:hover { text-decoration: none; color: var(--teal-soft); }
.brand:hover .brand-tagline { color: var(--bronze); }
/* The section row: centred under the wordmark, with the links set well apart —
   the spacing is what makes it read as a Cartier-style band rather than a
   huddle of tabs. */
.nav-links {
  display: flex;
  justify-content: center;
  gap: var(--space-9);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Tab labels are set in Georgia, matching the wordmark. */
.nav-links a {
  display: block;
  color: var(--ink);
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--nav-tab-size);
  letter-spacing: 0;
  /* Vertical breathing room around the label, and the tap target with it —
     comfortably past the 40px minimum the guide sets for a pointer. 15.6px is
     12px plus 30%; the active rule below tracks it, so the two stay locked. */
  padding: 15.6px 2px;
  transition: color .2s;
  position: relative;
}
.nav-links a:hover { color: var(--teal); text-decoration: none; }
/* The active section is marked the way the reference marks it: same colour,
   underlined. The rule is Dark Ruby — the accent's one job on this bar. */
/* The rule sits just under the label, not at the foot of the link. The link
   keeps its 12px of padding — that is the tap target, and shrinking it to move
   the rule would cost a pointer target to gain 2px of type — so the rule is
   lifted off the bottom edge instead. None of the tab words carry a
   descender, so it can sit this close without touching one. */
.nav-links a.active::after {
  content: "";
  position: absolute;
  /* Kept 2px under the padding edge, so it holds its distance from the label
     whatever the padding above is set to. */
  left: 0; right: 0; bottom: 17.6px;
  height: 2px;
  background: var(--ruby);
}
/* CR-03 — the count and the word sit on one centreline. A flex row centres
   them on each other whatever either one's font or size does; the old
   inline-block badge was aligned on the text baseline and rode low. */
.nav-cart {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink);
  font-family: var(--display);
  font-size: var(--nav-tab-size);   /* the word only — the bag and its count are sized in px */
  white-space: nowrap;
}
.nav-cart:hover { color: var(--teal); text-decoration: none; }
/* CR-03 — the word, the bag and the count all read off one centreline. Flex
   centring alone lines the word up with the icon BOX, whose middle falls in the
   handle; the bag's visual mass, and the count inside it, sit 4.2px lower. The
   remaining 0.5px is Georgia's descender room, which "Cart" has no letters in,
   so its ink rides that much above its own line box. Measured, not guessed. */
.nav-cart .cart-label { position: relative; top: 3.53px; }
/* A shopping bag rather than a filled disc, drawn in the link's own colour so
   it picks up the hover with the label. The count rides inside the bag: one
   mark instead of an icon with a badge stuck to it. */
.nav-cart .cart-bag {
  display: grid;
  place-items: center;
  width: 19.5px;
  height: 21px;
  flex: none;
}
.nav-cart .cart-bag svg {
  grid-area: 1 / 1;
  width: 19.5px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The badge is a count, not a word — it keeps Work Sans. It centres on the
   BODY of the bag, not on the icon box: the body runs y 10 → 26.4 of a 28-tall
   viewBox drawn 1:1, so its middle is 18.2 against the box's 14 — a 4.2px drop.
   Done with `top` rather than a margin, since a margin on a centred grid item
   only moves it half of what you write. Horizontally it already agrees: the
   body spans x 2.2 → 23.8, centred on 13, and so is the box. */
.nav-cart .count {
  grid-area: 1 / 1;
  position: relative;
  top: 3.15px;
  font-family: var(--body);
  font-size: 0.5rem;
  font-weight: 600;
  line-height: 1;
  color: currentColor;
}
.hamburger {
  grid-column: 1;
  justify-self: start;
  display: none;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 8px;
}
.hamburger span {
  display: block;
  width: 24px; height: 2px;
  background: var(--ink);
  margin: 5px 0;
  transition: transform .25s, opacity .25s;
}
.hamburger.open span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.hamburger.open span:nth-child(2){ opacity: 0; }
.hamburger.open span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }

/* Compact nav. This is NOT a breakpoint: js/main.js measures the section row
   against the bar's real width — including the gap it keeps at each end — and
   sets .compact only once the row genuinely stops fitting. A fixed width could
   not work, since the labels are set in a webfont that arrives after first
   paint and changes the row's width when it does. */
.site-nav.compact .hamburger { display: block; }
/* The dropdown hangs off the bottom of the bar itself, so it stays put
   whatever the bar's height turns out to be. */
.site-nav.compact .nav-links {
  position: absolute;
  top: 100%; left: 0; right: 0;
  flex-direction: column;
  justify-content: flex-start;
  gap: 0;
  margin: 0;
  background: var(--ivory);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 14px 24px rgba(7, 43, 49, 0.10);
  max-height: 0;
  overflow: hidden;
  transition: max-height .3s ease;
}
.site-nav.compact .nav-links.open { max-height: 460px; }
.site-nav.compact .nav-links a { padding: 14px 24px; text-align: center; }
.site-nav.compact .nav-links a.active::after { left: 24px; right: 24px; bottom: 16px; }

@media (max-width: 860px) {
  .brand-name { letter-spacing: 0.12em; }   /* size is fluid — see .brand-name */
  .brand-tagline { font-size: 0.6rem; letter-spacing: 0.06em; }
  .nav-links { gap: var(--space-8); }
}

/* Phones. The wordmark steps down so it clears the hamburger on one side and
   the cart on the other. The tagline keeps the size set above — it is already
   the widest element in the lockup and must never wrap. */
/* Smallest phones. The tagline — not the wordmark — is the widest thing in the
   lockup, and it must never wrap, so it is what steps down to keep the bar off
   a sideways scroll. */
@media (max-width: 400px) {
  .brand-tagline { font-size: 0.54rem; letter-spacing: 0.04em; }
}

@media (max-width: 520px) {
  .site-nav { padding: 11px 0 8px; }
  .nav-cart { gap: 6px; }   /* size still tracks the tabs, via --nav-tab-size */
}

/* ============================================================
   Page header / footer
   ============================================================ */
.page-head {
  /* 48px over the eyebrow, the same gap .customs-intro leaves under the bar,
     so every page still opens at the same height — moved off the old 34px,
     which was not on the 4px scale. */
  padding: var(--space-7) 0 var(--space-7);
  text-align: center;
}
/* Size and weight come from .lede; this only sets the measure and the tone. */
.page-head p.lede {
  max-width: 640px;
  margin: 0 auto;
  color: var(--muted);
}

/* CR-04 (Batch 2) — ivory, with the text reversed to Foundry Bronze. The band
   no longer separates itself from the page by its fill, so a rule along the top
   does that job instead. */
.site-footer {
  margin-top: var(--space-9);
  background: var(--ivory);
  color: var(--muted);
  border-top: 1px solid var(--line);
  padding: var(--space-7) 0;
  font-size: var(--fs-body-sm);
}
.site-footer .footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--page-pad);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
}
.site-footer .brand-sm {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: 0.14em;
  color: var(--cypress);
  text-transform: uppercase;
}


/* ============================================================
   Cards / grids (shared)
   ============================================================ */
.grid {
  display: grid;
  gap: var(--gutter);
}
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px){ .grid.cols-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px){ .grid.cols-3, .grid.cols-2 { grid-template-columns: 1fr; } }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .2s, box-shadow .2s;
}

/* Classics product card (PRD §3.2.1 – clean grid)
   White on Soft White with a hairline border and no resting shadow. The two
   grounds are now within ~1% of each other, so the border is doing all of the
   separating — worth knowing before anyone removes it. Hover does not lift the
   card; it casts the (10% ceiling) shadow and nothing else. */
.product-card { cursor: pointer; text-align: center; }
.product-card:hover { box-shadow: var(--shadow); }
.product-card .thumb { aspect-ratio: 1/1; background: var(--cream-2); }
.product-card .pc-body { padding: var(--space-5); }
.product-card .pc-name { font-family: var(--display); font-weight: 400; color: var(--navy); font-size: var(--fs-h4); line-height: 1.35; margin-bottom: var(--space-1); }
/* A price is figures, so it is set in Work Sans and never Georgia — Georgia's
   numerals are old-style and space unevenly down a column of prices. */
.product-card .pc-price { color: var(--muted); font-size: var(--fs-price); font-weight: 600; }

/* ============================================================
   Overlay / modal base (Customs widget – OQ-02 full-screen)
   ============================================================ */
.overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: rgba(20, 23, 45, 0.86);
  backdrop-filter: blur(4px);
  display: none;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  padding: var(--space-7) var(--space-5);
}
.overlay.open { display: flex; animation: fade-in .3s ease; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.overlay-close {
  position: fixed;
  top: 22px; right: 26px;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.08);
  color: #fff;
  cursor: pointer;
  z-index: 510;
  transition: background .2s;
  /* The button never centred its own content: a bare glyph in a button sits on
     the text baseline, which in a 44px circle reads low and slightly left. */
  display: grid;
  place-items: center;
  padding: 0;
}
.overlay-close svg {
  width: 24px; height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
}
.overlay-close:hover { background: rgba(255,255,255,0.2); }

/* utility */
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.divider { height: 1px; background: var(--line); margin: var(--space-7) 0; border: 0; }
/* Badges are squared, not pills — a pill carried too much weight for a row
   that can run to a dozen of them. One per card, maximum. */
.pill {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--track-support);
  padding: 6px 12px;
  border-radius: var(--radius);
}
.pill--active { background: var(--teal); color: var(--white); }
.pill--prospect { background: var(--cream-2); color: var(--muted); border: 1px solid var(--line); }
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); border:0; }

/* ============================================================
   Breakpoints (Style Guide §03)
   sm 0-767  ·  md 768-1023  ·  lg 1024-1439  ·  xl 1440+

   The scale is redefined on :root rather than per element, so every heading,
   gutter and page margin on the site steps down from these two blocks and
   nothing has to be told about a breakpoint twice.
   ============================================================ */
/* Tablet — 8 columns, 24px gutters, 40px margins. */
@media (max-width: 1023px) {
  :root { --page-pad: 40px; }
}
/* Phone — 4 columns, 16px gutters, 20px margins. Body sizes hold; only the
   display sizes come down, because a 64px headline on a 390px screen breaks
   into five words a line. */
@media (max-width: 767px) {
  :root {
    --page-pad: 20px;
    --gutter: 16px;
    --fs-display: 40px;
    --fs-h1: 32px;
    --fs-h2: 26px;
    --fs-h3: 22px;
    --fs-h4: 20px;
    --fs-lead: 18px;
  }
}
