/* VitalCare Essential Supplies Corp. — shared site styles */

:root{
  /* Palette drawn from the client's logo card: indigo → magenta → crimson ribbon */
  --paper:#FBF8FA;
  --paper-raised:#FFFFFF;
  --ink:#221C2E;
  --ink-soft:#6C6178;
  --crimson:#E31C3D;
  /* Brand crimson is only 4.42:1 on paper and 3.97:1 on blush — under the
     4.5:1 WCAG AA floor for body text. Fills keep the true brand colour
     (a background only needs 3:1); text links use this darker variant,
     which clears 4.5:1 on paper, white, and blush alike. */
  --link:#C81536;
  --crimson-deep:#7A1030;
  --navy:#2A1B68;
  --magenta:#96235F;
  --blush:#F7E9F0;
  --blush-strong:#EFD3E1;
  --line:#E7D9E6;
  --good:#2B764A;
  --focus:#2A1B68;
  --max:1180px;
}

*, *::before, *::after{ box-sizing:border-box; }
html{
  scroll-behavior:smooth;
  /* Clearance for the sticky header on anchor jumps. Deliberately small:
     every anchor target here is a section.block, which already carries 64px
     of its own top padding. At 96px the two stacked and the heading landed
     ~93px below the header — a dead gap that read as the scroll stopping
     short of its target. */
  scroll-padding-top:28px;
}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{
  font-family:"Iowan Old Style","Palatino Linotype","Book Antiqua",Georgia,serif;
  font-weight:600;
  line-height:1.25;
  text-wrap:balance;
  margin:0 0 .5em;
  color:var(--ink);
}
p{ margin:0 0 1em; }
img{ max-width:100%; display:block; }
a{ color:var(--link); }
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible{
  outline:2px solid var(--focus); outline-offset:3px;
}
.mono{
  font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;
  font-variant-numeric:tabular-nums;
}

.wrap{ max-width:var(--max); margin:0 auto; padding:0 24px; }
.table-wrap{ overflow-x:auto; }

/* ---------- Skip link ---------- */
.skip-link{
  position:absolute; left:-9999px; top:0;
  background:var(--navy); color:#fff; padding:10px 16px; z-index:200;
  border-radius:0 0 8px 0;
}
/* :focus-visible, not :focus. Back-to-top moves focus here so keyboard users
   resume from the top of the document, but with plain :focus that also popped
   the chip into view for anyone who clicked or tapped the button. */
.skip-link:focus-visible{ left:0; }

/* ---------- Top bar ---------- */
.topbar{
  background:linear-gradient(90deg, var(--navy), var(--crimson-deep) 70%);
  color:#F3E1EC;
  font-size:.82rem;
}
.topbar .wrap{
  display:flex; flex-wrap:wrap; gap:6px 20px;
  justify-content:space-between;
  padding-top:8px; padding-bottom:8px;
}
.topbar a{ color:#F8E6F0; text-decoration:none; }
.topbar a:hover{ text-decoration:underline; }
.topbar .hours{ opacity:.9; }

/* ---------- Header / nav ---------- */
header.site{
  background:var(--paper-raised);
  border-bottom:1px solid var(--line);
  position:sticky; top:0; z-index:100;
}
.nav-row{
  display:flex; align-items:center; justify-content:space-between;
  /* .nav-row and .wrap are the same element, so a shorthand here replaces
     .wrap's horizontal padding outright. It previously read `14px 0`, which
     silently zeroed the gutter and left the logo and toggle hard against the
     screen edges while every other section sat 24px in. */
  padding:14px 24px;
  gap:20px;
}
.brand{
  display:flex; align-items:center; gap:10px;
  text-decoration:none; color:var(--ink);
  flex:none;
}
.brand svg, .brand img{ width:38px; height:38px; flex:none; object-fit:contain; }
.brand-text{ display:flex; flex-direction:column; line-height:1.15; }
.brand-text strong{ font-family:"Iowan Old Style","Palatino Linotype","Book Antiqua",Georgia,serif; font-size:1.05rem; }
.brand-text span{ font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; color:var(--ink-soft); }

nav.primary{ display:flex; align-items:center; gap:2px; }
nav.primary a{
  color:var(--ink-soft); text-decoration:none; font-size:.92rem;
  padding:9px 12px; border-radius:7px;
}
nav.primary a:hover{ color:var(--ink); background:var(--blush); }
nav.primary a[aria-current="page"]{ color:var(--ink); font-weight:600; }
nav.primary a.cta{
  background:var(--crimson); color:#fff; font-weight:600;
  padding:9px 16px; margin-left:6px;
}
nav.primary a.cta:hover{ background:var(--crimson-deep); color:#fff; }

.nav-toggle{
  display:none;
  background:none; border:1px solid var(--line); border-radius:8px;
  width:42px; height:42px; cursor:pointer;
  align-items:center; justify-content:center;
}
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after{
  content:""; display:block; width:20px; height:2px; background:var(--ink);
  position:relative; transition:transform .15s ease, opacity .15s ease;
}
.nav-toggle span::before{ position:absolute; top:-6px; }
.nav-toggle span::after{ position:absolute; top:6px; }

/* Switch to the hamburger at 910px rather than 860px. The five horizontal
   items plus the brand only stop wrapping to a second line at 911px once the
   nav row carries the same 24px gutter as the rest of the page — measured,
   not guessed. Other 860px rules govern unrelated layout and stay put. */
@media (max-width:910px){
  .nav-toggle{ display:flex; }
  nav.primary{
    position:absolute; top:100%; left:0; right:0;
    background:var(--paper-raised);
    border-bottom:1px solid var(--line);
    flex-direction:column; align-items:stretch;
    /* Same 24px gutter as everything else, so menu items line up with the
       logo above them. */
    padding:8px 24px 16px;
    display:none;
  }
  nav.primary.open{ display:flex; }
  nav.primary a{ padding:12px 8px; border-radius:0; border-bottom:1px solid var(--line); }
  nav.primary a.cta{ margin:10px 0 0; text-align:center; border-radius:8px; border-bottom:none; }
}

/* ---------- Auto-hiding header (phones + tablets) ---------- */
/* Reclaims vertical space while reading: the bar retreats on the way down and
   comes straight back on any upward scroll. Desktop keeps a permanently
   sticky header — there's enough room there that hiding it only costs
   navigation. */
@media (max-width:1080px){
  header.site{
    position:sticky; top:0;
    transition:transform .25s ease;
    will-change:transform;
  }
  header.site.nav-hidden{ transform:translateY(-100%); }
  /* Never hide while the mobile menu is open. */
  header.site.nav-open{ transform:none; }
}
@media (prefers-reduced-motion:reduce){
  header.site{ transition:none; }
}

/* ---------- Hero ---------- */
.hero{
  background:var(--blush);
  border-bottom:1px solid var(--line);
  position:relative;
  overflow:hidden;
}
.hero .wrap{
  position:relative;
  z-index:1;
  padding:64px 24px;
  display:grid;
  grid-template-columns:1.1fr .9fr;
  gap:40px;
  align-items:center;
}
/* 24px matches .wrap everywhere else, so the logo, hero copy, section
   headings and footer all share one gutter down the left edge. */
@media (max-width:860px){ .hero .wrap{ grid-template-columns:1fr; padding:44px 24px; } }
.eyebrow{
  text-transform:uppercase; letter-spacing:.12em; font-size:.72rem;
  font-weight:700; color:var(--navy); margin:0 0 10px;
}
.hero h1{ font-size:clamp(1.9rem,3.6vw,2.7rem); margin-bottom:.35em; }
.hero .lede{ font-size:1.05rem; color:var(--ink-soft); max-width:52ch; margin-bottom:1.4em; }
.hero-actions{ display:flex; flex-wrap:wrap; gap:12px; }
.hero-panel{
  background:var(--paper-raised);
  border:1px solid var(--line);
  border-radius:14px;
  padding:26px 28px;
}
.hero-panel h2{ font-size:1rem; margin-bottom:14px; }
.hero-panel ul{ margin:0; padding-left:20px; font-size:.92rem; color:var(--ink-soft); display:flex; flex-direction:column; gap:8px; }

/* ---------- Brand flourish (fan-ribbon motif from the logo card) ---------- */
/* Soft in opacity so it never fights the text — but let the ribbon actually
   reach; the coordinate space (140x140, see petal viewBox) has enough room
   for every blade to taper to its own point instead of hitting a hard edge. */
.corner-flourish, .fan-flourish{
  position:absolute;
  pointer-events:none;
  z-index:0;
  overflow:hidden;
}
/* Sized against the viewport, not fixed px. At a locked 290px the fan sat
   behind the hero heading and lede on tablets, where .wrap padding is small
   and the text starts near the corner. Scaling with vw keeps it a corner
   accent at every width. Container opacity trims it further behind text. */
.corner-flourish{ width:clamp(96px, 13vw, 170px); height:clamp(96px, 13vw, 170px); opacity:.85; }
.corner-flourish.tl{ top:-20px; left:-20px; }
.corner-flourish.br{ bottom:-20px; right:-20px; transform:rotate(180deg); }

.fan-flourish{ width:clamp(150px, 19vw, 290px); height:clamp(150px, 19vw, 290px); opacity:.8; }
.fan-flourish.tl{ top:-34px; left:-34px; }
.fan-flourish.br{ bottom:-34px; right:-34px; transform:rotate(180deg); }

.flourish-blade{
  transform-box:fill-box;
  transform-origin:0 0;
  transform:rotate(var(--rot,0deg)) scale(var(--scale,1));
  opacity:var(--op,.5);
}

/* Every flourish gets a one-time reveal on load, then settles into a slow idle drift.
   The idle drift alone (rotate ~2-3deg, scale ~3-5%, over 10s) is too subtle to read as
   "animated" on its own — the reveal is what actually makes the motion visible. */
@keyframes flourish-open{
  from{ transform:rotate(0deg) scale(.3); opacity:0; }
  to{ transform:rotate(var(--rot,0deg)) scale(var(--scale,1)); opacity:var(--op,.55); }
}
@keyframes blade-breathe{
  from{ transform:rotate(var(--rot,0deg)) scale(var(--scale,1)); }
  to{ transform:rotate(calc(var(--rot,0deg) + 3deg)) scale(calc(var(--scale,1) * 1.05)); }
}

.corner-flourish .flourish-blade{
  opacity:0;
  animation-name:flourish-open, blade-breathe;
  animation-duration:.6s, 10s;
  animation-timing-function:cubic-bezier(.16,.84,.44,1), ease-in-out;
  animation-iteration-count:1, infinite;
  animation-direction:normal, alternate;
  animation-fill-mode:both, none;
  animation-delay:var(--open-delay,0s), calc(var(--open-delay,0s) + .6s);
}

/* Home hero: a bigger, slightly slower unfurl into its fan, then the same idle drift */
.fan-flourish .flourish-blade{
  opacity:0;
  animation-name:flourish-open, blade-breathe;
  animation-duration:.9s, 10s;
  animation-timing-function:cubic-bezier(.16,.84,.44,1), ease-in-out;
  animation-iteration-count:1, infinite;
  animation-direction:normal, alternate;
  animation-fill-mode:both, none;
  animation-delay:var(--open-delay,0s), calc(var(--open-delay,0s) + .9s);
}

@media (prefers-reduced-motion:reduce){
  .corner-flourish .flourish-blade,
  .fan-flourish .flourish-blade{
    animation:none;
    opacity:var(--op,.5);
  }
}

/* ---------- Back to top ---------- */
.to-top{
  position:fixed;
  right:20px; bottom:20px;
  z-index:90;
  width:46px; height:46px;
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line);
  border-radius:50%;
  background:var(--paper-raised);
  color:var(--ink);
  box-shadow:0 3px 14px rgba(34,28,46,.16);
  cursor:pointer;
  /* Hidden until scrolled; kept out of the tab order and the a11y tree while
     hidden so it isn't a phantom stop for keyboard and screen-reader users. */
  opacity:0; visibility:hidden; transform:translateY(8px);
  transition:opacity .2s ease, transform .2s ease, visibility .2s;
}
.to-top.is-visible{ opacity:1; visibility:visible; transform:none; }
.to-top:hover{ background:var(--blush); border-color:var(--ink-soft); }
.to-top svg{ width:19px; height:19px; display:block; }
@media (max-width:860px){
  .to-top{ right:16px; bottom:16px; width:44px; height:44px; }
}
@media (prefers-reduced-motion:reduce){
  .to-top{ transition:none; }
}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex; align-items:center; gap:8px;
  padding:12px 20px; border-radius:9px;
  font-size:.94rem; font-weight:600; text-decoration:none;
  border:1px solid transparent; cursor:pointer;
}
.btn-primary{ background:var(--crimson); color:#fff; }
.btn-primary:hover{ background:var(--crimson-deep); }
.btn-ghost{ background:transparent; color:var(--ink); border-color:var(--line); }
.btn-ghost:hover{ background:var(--paper-raised); border-color:var(--ink-soft); }

/* ---------- Sections ---------- */
section.block{ padding:64px 0; }
section.block.tight{ padding:44px 0; }
section.block.alt{ background:var(--paper-raised); border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.section-head{ max-width:70ch; margin-bottom:34px; }
.section-head h2{ font-size:1.6rem; }
.section-head p{ color:var(--ink-soft); margin:0; }

/* ---------- Long-form text (privacy, terms) ----------
   Stacked by default: heading, then its copy, full width. A capped measure
   alone would have been readable but left half a desktop screen empty,
   which reads as a broken layout rather than a deliberate one -- so above
   1024px each section splits into a heading rail and a body column (see
   the media query below). The copy column keeps the readable measure
   either way; the width goes to structure instead of longer lines. */
.prose-section{ margin-bottom:34px; }
.prose h2{
  font-size:1.15rem;
  margin:0 0 10px;
}
.prose p{ color:var(--ink-soft); margin:0 0 14px; max-width:68ch; }
.prose p:last-child{ margin-bottom:0; }
.prose ul{ color:var(--ink-soft); margin:0; padding-left:20px; max-width:68ch; }
.prose li{ margin-bottom:6px; }
.prose li:last-child{ margin-bottom:0; }
.prose .policy-updated{
  margin-top:38px;
  padding-top:18px;
  border-top:1px solid var(--line);
  font-size:.85rem;
}

@media (min-width:1025px){
  .prose-section{
    display:grid;
    /* The rail is wide enough for two or three words per line, which keeps
       the longest heading here from towering over its own paragraph. */
    grid-template-columns:minmax(0,15rem) minmax(0,1fr);
    column-gap:48px;
    margin-bottom:42px;
  }
  .prose-section h2{
    /* Optically aligns the heading with the first line of body text beside
       it -- the two have different line-heights, so matching the box tops
       leaves the heading sitting slightly high. */
    margin-top:2px;
  }
  .prose .policy-updated{
    /* Line the footnote up under the body column, not the rail. */
    margin-left:calc(15rem + 48px);
  }
}

/* ---------- Cards / grids ---------- */
.grid{ display:grid; gap:18px; }
.grid-2{ grid-template-columns:repeat(2,1fr); }
.grid-3{ grid-template-columns:repeat(3,1fr); }
.grid-4{ grid-template-columns:repeat(4,1fr); }
@media (max-width:860px){ .grid-2, .grid-3, .grid-4{ grid-template-columns:1fr; } }
@media (min-width:861px) and (max-width:1080px){ .grid-3, .grid-4{ grid-template-columns:repeat(2,1fr); } }

/* Dense grids of short product cards stay 2-up on phones. Stacking 16 of them
   single-column produced a ~15,000px page — far too long to browse.
   Two classes beats the single-class rule above, so no !important needed. */
@media (max-width:860px){
  .grid.grid-compact{ grid-template-columns:repeat(2,1fr); gap:12px; }
  .grid.grid-compact .card{ padding:16px 16px 18px; }
  .grid.grid-compact .card h3{ font-size:.92rem; }
  .grid.grid-compact .card p{ font-size:.8rem; }
  .grid.grid-compact .card-img{ margin:-16px -16px 12px; }
}

.card{
  background:var(--paper-raised);
  border:1px solid var(--line);
  border-radius:12px;
  padding:22px 24px;
  overflow:hidden;
}
.card h2, .card h3{ font-size:1rem; margin-bottom:8px; }
.card p{ font-size:.9rem; color:var(--ink-soft); margin:0; }
.card p + p{ margin-top:8px; }

/* Fax and phone each get their own line — side by side they wrapped awkwardly
   mid-number on narrow screens. */
.contact-lines{
  list-style:none; margin:12px 0 0; padding:0;
  display:flex; flex-direction:column; gap:4px;
  font-size:.9rem; color:var(--ink-soft);
}
.contact-lines span, .contact-lines a{ color:var(--ink); }

/* Placeholder product photo slot — drop an <img> in place of the text and it fills the same box */
.card-img{
  aspect-ratio:4/3;
  margin:-22px -24px 16px;
  background:var(--blush);
  display:flex;
  align-items:center;
  justify-content:center;
  color:var(--ink-soft);
  font-size:.68rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.08em;
}
/* The <picture> wrapper is transparent to layout, so the <img> inside it
   still sizes against .card-img itself. Without this the picture becomes
   the flex item and the image sizes against that instead, collapsing the
   4:3 box. */
.card-img picture{ display:contents; }
.card-img img{ width:100%; height:100%; object-fit:cover; display:block; }

/* Prompt below the category browser — a text link rather than a button, so
   it reads as guidance, not nagging. */
.cat-cta{
  margin:18px 0 0;
  font-size:.88rem;
  color:var(--ink-soft);
}

/* ---------- Shortlist ----------
   Not a cart — nothing is sold here. Saving a product just adds its id to
   localStorage (see main.js); this panel re-reads and re-renders from
   whatever's saved, and the "Email us" link is a mailto: with the list
   spelled out, since there's no backend to submit an inquiry form to.
   Lives inside .cat-toolbar (see below) rather than above .cat-browser,
   so it sits in the same row as search and the view toggle; the panel
   is positioned absolutely so opening it doesn't push its toolbar
   siblings around. */
.shortlist{ position:relative; }
.shortlist-toggle{
  all:unset;
  box-sizing:border-box;
  cursor:pointer;
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:10px 18px;
  border:1px solid var(--line);
  border-radius:20px;
  font-size:.88rem;
  font-weight:600;
  color:var(--ink);
}
.shortlist-toggle:hover{ background:var(--blush); }
.shortlist-toggle:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.shortlist-toggle .shortlist-count{
  background:var(--crimson);
  color:#fff;
  border-radius:10px;
  padding:1px 8px;
  font-size:.78rem;
}
.shortlist-panel{
  position:absolute;
  top:calc(100% + 10px);
  left:0;
  z-index:5;
  width:min(360px, 90vw);
  max-height:70vh;
  overflow-y:auto;
  border:1px solid var(--line);
  border-radius:12px;
  padding:18px 20px;
  background:var(--paper-raised);
  box-shadow:0 12px 32px rgba(34,28,46,.16);
}
.shortlist-empty{ margin:0; color:var(--ink-soft); font-size:.9rem; }
.shortlist-items{ display:flex; flex-direction:column; gap:10px; }
.shortlist-items .cat-item{
  display:grid;
  grid-template-columns:72px 1fr auto;
  grid-template-rows:auto auto auto;
  column-gap:12px;
  align-items:start;
  padding:10px 12px;
}
.shortlist-items .cat-item .card-img{
  grid-column:1;
  grid-row:1 / 4;
  align-self:center;
  width:72px;
  aspect-ratio:4/3;
  margin:0;
  border-radius:8px;
  /* Clips the thumbnail to the rounded corners — without this the <img>
     renders square inside a rounded box. */
  overflow:hidden;
  font-size:0;
}
.shortlist-item-category{
  grid-column:2;
  grid-row:1;
  margin:0;
  font-size:.68rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.06em;
  color:var(--navy);
}
.shortlist-items .cat-item h3{ grid-column:2; grid-row:2; font-size:.88rem; margin:2px 0 0; }
.shortlist-items .cat-item p{ grid-column:2; grid-row:3; margin:4px 0 0; }
/* A special request has no photo to show, so it drops the 72px image
   column entirely rather than leaving a gap where one would sit. */
.shortlist-items .cat-item.is-custom{ grid-template-columns:1fr auto; }
.shortlist-items .cat-item.is-custom .shortlist-item-category,
.shortlist-items .cat-item.is-custom h3,
.shortlist-items .cat-item.is-custom p{ grid-column:1; }
.shortlist-items .cat-item.is-custom .shortlist-remove{ grid-column:2; }

.shortlist-remove{
  all:unset;
  box-sizing:border-box;
  grid-column:3;
  grid-row:1 / 4;
  align-self:center;
  cursor:pointer;
  width:28px;
  height:28px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:50%;
  color:var(--ink-soft);
  font-size:1.1rem;
}
.shortlist-remove:hover{ background:var(--blush); color:var(--ink); }
.shortlist-remove:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.shortlist-actions{ display:flex; flex-wrap:wrap; gap:10px; margin-top:16px; }
.shortlist-actions .btn{ padding:10px 18px; font-size:.88rem; }

/* ---------- Product category browser ---------- */
.cat-browser{
  display:grid;
  grid-template-columns:230px 1fr;
  gap:32px;
  align-items:start;
}
.cat-nav{
  display:flex;
  flex-direction:column;
  gap:2px;
  /* A plain list at this width — no sticky pin, no internal scroll. It's
     just as tall as its 17 categories and scrolls with the rest of the
     page, same as the product grid beside it. */
}

/* Category picker shown only on narrower screens (see the ≤860px media
   query below), where a 17-item list would push the grid off the first
   screen. Hidden by default so the tablist above is what desktop/tablet
   users see. */
.cat-select{
  display:none;
  width:100%;
  box-sizing:border-box;
  padding:12px 14px;
  border:1px solid var(--line);
  border-radius:10px;
  background:var(--paper-raised);
  font:inherit;
  font-size:.92rem;
  color:var(--ink);
  cursor:pointer;
}
.cat-select:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.cat-nav button{
  all:unset;
  box-sizing:border-box;
  cursor:pointer;
  padding:11px 14px;
  border-radius:8px;
  font-size:.86rem;
  line-height:1.3;
  color:var(--ink-soft);
}
.cat-nav button:hover{ background:var(--blush); color:var(--ink); }
.cat-nav button[aria-selected="true"]{
  background:var(--blush-strong);
  color:var(--ink);
  font-weight:600;
}
.cat-nav button:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }

.cat-content{ min-width:0; }
.cat-panel[hidden]{ display:none; }

.visually-hidden{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
}

/* Shortlist, search, and the grid/list toggle share one row on wide
   screens and wrap onto their own lines on narrow ones — space-between
   naturally reads as "shortlist left, view toggle right" with search
   filling the middle, and .cat-search's flex-basis lets it claim the
   most room without the other two growing past their content size. */
.cat-toolbar{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  margin-bottom:14px;
}
.cat-toolbar .shortlist,
.cat-toolbar .view-toggle{ flex:0 0 auto; }
.cat-search{
  position:relative;
  flex:1 1 240px;
  max-width:360px;
}
.cat-search-input{
  box-sizing:border-box;
  width:100%;
  padding:9px 34px 9px 14px;
  border:1px solid var(--line);
  border-radius:20px;
  font-size:.88rem;
  font-family:inherit;
  color:var(--ink);
  background:var(--paper-raised);
}
.cat-search-input::placeholder{ color:var(--ink-soft); }
.cat-search-input:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
/* Native WebKit/Edge "clear" glyphs are dropped in favour of the one
   .cat-search-clear button below, so there's a single consistent control
   instead of two overlapping ones at different positions per browser. */
.cat-search-input::-webkit-search-cancel-button{ -webkit-appearance:none; appearance:none; }
.cat-search-clear{
  all:unset;
  position:absolute;
  right:6px; top:50%;
  transform:translateY(-50%);
  box-sizing:border-box;
  width:24px; height:24px;
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  border-radius:50%;
  color:var(--ink-soft);
  font-size:1.1rem;
  line-height:1;
}
/* all:unset above resets display along with everything else, so the
   hidden attribute's native display:none needs restating here — otherwise
   the display:flex two lines up would win and show the button regardless
   of the attribute. */
.cat-search-clear[hidden]{ display:none; }
.cat-search-clear:hover{ background:var(--blush); color:var(--ink); }
.cat-search-clear:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }

.search-results[hidden]{ display:none; }

/* ---------- Request an unstocked item ----------
   Only rendered when a search finds nothing (main.js toggles [hidden]).
   Adding one puts it on the same shortlist as catalog products, so the
   existing "Email us this list" covers both in one message. */
.request-card{
  border:1px solid var(--line);
  border-radius:12px;
  background:var(--blush);
  padding:20px 22px;
  /* Sits at the end of the browser, so the gap goes above it -- it needs
     separating from the catalog it follows, not from what comes after. */
  margin-top:26px;
}
.request-card h3{ font-size:1.05rem; margin:0 0 6px; }
.request-card > p{
  margin:0 0 14px;
  font-size:.9rem;
  color:var(--ink-soft);
  max-width:62ch;
}
.request-row{ display:flex; gap:8px; align-items:stretch; }
.request-input{
  flex:1 1 auto;
  min-width:0;
  box-sizing:border-box;
  padding:10px 14px;
  border:1px solid var(--line);
  border-radius:20px;
  background:var(--paper-raised);
  font-size:.9rem;
  font-family:inherit;
  color:var(--ink);
}
.request-input::placeholder{ color:var(--ink-soft); }
.request-input:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.request-add{
  all:unset;
  box-sizing:border-box;
  flex:none;
  width:42px;
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  border-radius:50%;
  background:var(--crimson);
  color:#fff;
  font-size:1.4rem;
  line-height:1;
}
.request-add:hover{ background:var(--crimson-deep); }
.request-add:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.request-feedback{
  margin:10px 0 0;
  min-height:1.2em;            /* reserve the line so adding doesn't shift the card */
  font-size:.84rem;
  color:var(--good);
}
.search-status{
  margin:0 0 12px;
  font-size:.84rem;
  color:var(--ink-soft);
}
/* Each result card gets a category chip the tabbed view doesn't need,
   since results are pulled from every category at once. Positioned over
   the photo's own top-left corner (mirroring .save-btn's top-right) rather
   than sitting in normal flow above it -- .card-img carries a negative
   top margin to bleed flush with the card edge, so anything placed before
   it in flow gets pulled up and clipped underneath it. */
.search-grid .cat-item-category{
  position:absolute;
  top:8px;
  left:8px;
  z-index:1;
  padding:3px 10px;
  border-radius:20px;
  background:rgba(255,255,255,.9);
  color:var(--magenta);
  font-size:.68rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.02em;
}

/* Grid vs. list is a global choice (not tied to a breakpoint) — the two
   buttons just toggle .is-list on .cat-panels, which every rule below keys
   off of. */
.view-toggle{
  display:flex;
  gap:8px;
}
.view-toggle .view-btn{
  all:unset;
  box-sizing:border-box;
  cursor:pointer;
  padding:8px 16px;
  border:1px solid var(--line);
  border-radius:20px;
  font-size:.84rem;
  color:var(--ink-soft);
}
.view-toggle .view-btn:hover{ background:var(--blush); color:var(--ink); }
.view-toggle .view-btn[aria-pressed="true"]{
  background:var(--blush-strong);
  color:var(--ink);
  font-weight:600;
  border-color:var(--crimson);
}
.view-toggle .view-btn:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }

.cat-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:12px;
}
.cat-item{
  position:relative;
  border:1px solid var(--line);
  border-radius:10px;
  background:var(--paper-raised);
  padding:16px 18px;
  overflow:hidden;
}
.cat-item h3{ font-size:.94rem; margin:0 0 5px; }
.cat-item p{ font-size:.84rem; color:var(--ink-soft); margin:0; }
.cat-item .card-img{ margin:-16px -18px 12px; }

/* The product name is a real <button> so the show/hide of the description
   below it is operable by keyboard, not just by tapping the card. It has to
   look like plain heading text -- `all:unset` drops the UA button styling and
   lets it inherit the h3's own font, so this is purely a semantics change. */
.cat-item-toggle{
  all:unset;
  box-sizing:border-box;
  display:block;
  width:100%;
  cursor:pointer;
  font:inherit;
  color:inherit;
}
.cat-item-toggle:focus-visible{ outline:2px solid var(--focus); outline-offset:3px; }

/* Sits over the photo's top-right corner in grid view; in list view (see
   below) the row is short enough that the same top/right offset lands it
   beside the name instead — no separate positioning rule needed either
   way, just breathing room reserved on the list-view name so long titles
   don't run under it. */
.save-btn{
  all:unset;
  box-sizing:border-box;
  position:absolute;
  top:8px;
  right:8px;
  z-index:1;
  cursor:pointer;
  width:30px;
  height:30px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:50%;
  background:rgba(255,255,255,.85);
  color:var(--ink-soft);
  font-size:1.05rem;
  line-height:1;
}
.save-btn:hover{ color:var(--crimson); }
.save-btn:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.save-btn[aria-pressed="true"]{ color:var(--crimson); }

/* ---------- List view ----------
   Same three children (.card-img, h3, p) as grid view — just re-placed
   with explicit grid-column/row instead of relying on source order, so no
   markup changes were needed to support this mode. Collapsed rows clip to
   a name-only strip via max-height; opening one sets an inline max-height
   from the row's real scrollHeight (in main.js) so the reveal can animate
   smoothly without knowing the content's height in advance. */
.cat-panels.is-list .cat-grid{ grid-template-columns:1fr; gap:8px; }
.cat-panels.is-list .cat-item{
  display:grid;
  grid-template-columns:88px 1fr;
  column-gap:12px;
  align-items:start;
  padding:10px 12px;
  /* Collapsed height is the name plus this row's 20px of padding. It used
     to be a flat 44px, which assumed every name fit on one line -- at
     390px "Back Support with Removable Side Panels" wraps to two and at
     320px a few reach three, so the extra lines were sliced through and
     the photo below bled into the overflow.
     --collapsed-h is measured per row in main.js (the browser can't know
     how many lines a name wraps to from CSS alone); the calc is the
     fallback for the first paint before that runs, and for no-JS. */
  max-height:var(--collapsed-h, calc(1.4em + 20px));
  overflow:hidden;
  cursor:pointer;
}
/* The transition is withheld until main.js has measured real collapsed
   heights (.has-measured), and switched off again around any re-measure
   (.is-resizing). Both guard the same thing: --collapsed-h changing for
   every card at once is a layout correction, not someone opening a card,
   and animating it made page loads look like the cards were closing
   themselves and view switches look like the whole list furling shut. */
.cat-panels.has-measured.is-list .cat-item{ transition:max-height .25s ease; }
.cat-panels.is-resizing.is-list .cat-item{ transition:none; }
.cat-panels.is-list .cat-item h3{
  grid-column:1 / -1;
  grid-row:1;
  margin:0;
  padding-right:34px;
  line-height:1.4;
}
.cat-panels.is-list .cat-item .card-img{
  grid-column:1;
  grid-row:2;
  width:88px;
  margin:10px 0 0;
  border-radius:8px;
  font-size:0;
}
.cat-panels.is-list .cat-item p{
  grid-column:2;
  grid-row:2;
  margin:10px 0 0;
}

/* Grid view only — list view has nothing to page since every row is
   already just a name. Hidden whenever a category fits on one page. */
.cat-pager{
  display:none;
  align-items:center;
  justify-content:center;
  gap:16px;
  margin-top:20px;
}
.cat-pager .pager-btn{
  all:unset;
  box-sizing:border-box;
  cursor:pointer;
  width:36px;
  height:36px;
  display:flex;
  align-items:center;
  justify-content:center;
  border:1px solid var(--line);
  border-radius:50%;
  color:var(--ink);
}
.cat-pager .pager-btn:hover{ background:var(--blush); }
.cat-pager .pager-btn:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.cat-pager .pager-btn:disabled{ opacity:.35; cursor:not-allowed; }
.cat-pager .pager-btn:disabled:hover{ background:none; }
.cat-pager .pager-status{ font-size:.86rem; color:var(--ink-soft); }

.cat-empty{
  border:1px dashed var(--line);
  border-radius:12px;
  padding:38px 22px;
  text-align:center;
  color:var(--ink-soft);
  font-size:.9rem;
  line-height:1.7;
}

@media (max-width:860px){
  .cat-browser{ grid-template-columns:1fr; gap:16px; }
  /* A vertical list of 17 categories would push the grid below the fold on
     a phone or portrait tablet before showing a single product, so the
     tablist is swapped for a native dropdown at this width instead. */
  .cat-nav{ display:none; }
  .cat-select{ display:block; }
  .cat-grid{ grid-template-columns:repeat(2,1fr); }

  /* Grid view only: description stays off until the card is tapped, to
     keep the compact 2-up layout scannable. List view already handles its
     own show/hide via the accordion rules above, so it's excluded here.

     Collapsed by animating the card's own max-height, the same way list
     view does, rather than display:none on the <p>. display isn't an
     animatable property, so the old rule snapped the card open in a single
     frame. Animating the card itself (rather than collapsing a grid track)
     is deliberate: the card stays a block, so cards sharing a row keep
     their own heights and opening one can't stretch or shift its
     neighbour.

     --collapsed-h is measured per card in main.js; the calc fallback
     covers the first paint and no-JS. */
  .cat-panels:not(.is-list) .cat-item{
    max-height:var(--collapsed-h, 15rem);
    overflow:hidden;
    cursor:pointer;
  }
  /* Same reasoning as list view: no transition until real heights exist,
     and none around a re-measure, or the correction animates on every
     load and every view switch. */
  .cat-panels.has-measured:not(.is-list) .cat-item{ transition:max-height .25s ease; }
  .cat-panels.is-resizing:not(.is-list) .cat-item{ transition:none; }
  .cat-panels:not(.is-list) .cat-item.is-expanded{ max-height:var(--expanded-h, 40rem); }
  .cat-panels:not(.is-list) .cat-item p{ margin-top:6px; }
  /* The card's bottom padding leaves ~17px below the name, and the
     description starts inside it -- enough for its first line to show
     through a collapsed card. visibility (not display) hides it without
     taking it out of layout, so scrollHeight still measures the full open
     height and the reveal keeps its animation. */
  .cat-panels:not(.is-list) .cat-item:not(.is-expanded) p{ visibility:hidden; }

  /* Shortlist rows: the 1fr text column is narrow enough here that the
     category label wraps to two lines squeezed beside the photo. Giving it
     its own full-width row across the whole card fixes that and pushes
     everything else down a row to make room. */
  .shortlist-item-category{ grid-column:1 / -1; grid-row:1; }
  .shortlist-items .cat-item .card-img{ grid-row:2 / 4; }
  .shortlist-items .cat-item h3{ grid-row:2; }
  .shortlist-items .cat-item p{ grid-row:3; }
  .shortlist-remove{ grid-row:2 / 4; }
}

@media (min-width:861px) and (max-width:1080px){
  .cat-browser{ grid-template-columns:190px 1fr; gap:22px; }
}

.tile{
  background:var(--blush);
  border-radius:12px;
  padding:20px 22px 22px;
}
.tile h3{ font-size:.95rem; margin-bottom:10px; }
.tile ul{ margin:0; padding-left:18px; font-size:.87rem; color:var(--ink-soft); display:flex; flex-direction:column; gap:5px; }

/* ---------- Process flow ---------- */
.flow{ display:grid; grid-template-columns:repeat(4,1fr); counter-reset:step; }
@media (max-width:780px){ .flow{ grid-template-columns:1fr; } }
.flow-step{ position:relative; padding:18px 18px 4px 0; border-top:2px solid var(--crimson); }
.flow-step + .flow-step{ padding-left:18px; }
@media (max-width:780px){
  .flow-step{ border-top:none; border-left:2px solid var(--crimson); padding:12px 0 12px 18px; }
  .flow-step + .flow-step{ padding-left:18px; }
}
.flow-step::before{
  counter-increment:step; content:counter(step);
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:50%;
  background:var(--navy); color:#fff; font-size:.78rem; font-weight:700;
  margin-bottom:10px;
}
.flow-step h3{ font-size:.98rem; margin-bottom:6px; }
.flow-step p{ font-size:.87rem; color:var(--ink-soft); margin:0; }

/* ---------- Mission / dark panel ---------- */
.panel-dark{
  background:linear-gradient(135deg, var(--navy), var(--crimson-deep) 85%);
  color:#F4E9E7;
  border-radius:16px;
  padding:40px 42px;
  position:relative;
  overflow:hidden;
}
.panel-dark .eyebrow{ color:#E9B7CB; position:relative; }
.panel-dark h2{ color:#fff; position:relative; }
/* Cap the measure: full-bleed inside a wide panel ran to ~131ch on desktop,
   well past the ~65-75ch that stays comfortable to read. */
.panel-dark p{ color:#F0DAD8; position:relative; max-width:66ch; }
.panel-dark .tagline{ position:relative; }
.panel-dark .tagline{
  display:inline-flex; font-size:.8rem; font-weight:700; letter-spacing:.03em;
  background:rgba(255,255,255,.13); padding:8px 16px; border-radius:20px;
}
.panel-actions{ position:relative; display:flex; flex-wrap:wrap; gap:12px; }
/* Outlined button for use on the dark panel — white on both ends of the
   navy→crimson gradient clears AA comfortably. */
.btn-onDark{
  background:transparent; color:#fff; border-color:rgba(255,255,255,.5);
}
.btn-onDark:hover{ background:rgba(255,255,255,.12); border-color:#fff; }

/* ---------- Table ---------- */
table.data{ width:100%; border-collapse:collapse; font-size:.92rem; }
table.data th{
  text-align:left; font-size:.7rem; text-transform:uppercase; letter-spacing:.08em;
  color:var(--ink-soft); padding:0 14px 10px 0; border-bottom:1px solid var(--line);
}
table.data td{ padding:14px 14px 14px 0; border-bottom:1px solid var(--line); vertical-align:top; }
table.data tr:last-child td{ border-bottom:none; }

.badge{
  display:inline-block; font-size:.68rem; text-transform:uppercase; letter-spacing:.06em;
  font-weight:700; padding:3px 10px; border-radius:20px;
  background:var(--blush-strong); color:var(--ink);
}
.badge.navy{ background:var(--navy); color:#fff; }
.badge.crimson{ background:var(--crimson); color:#fff; }
.badge.good{ background:#DDEFE3; color:var(--good); }

/* Hours table inside a card: keep day and time each on one line. Scoped to
   .card so the wider insurance table elsewhere can still wrap normally. */
.card table.data td{ white-space:nowrap; }
@media (max-width:420px){
  .card table.data{ font-size:.85rem; }
  .card table.data td{ padding-right:8px; }
}

/* Headings that are themselves links (404 cards) — 22px is under the 24px
   minimum at every width, so this is not viewport-conditional. */
.card h3 a{ display:inline-block; padding:4px 0; }

/* ---------- Touch tap targets ---------- */
/* Keyed on pointer:coarse as well as width. Scoping this to max-width:860px
   alone missed tablets: an iPad at 1024px is a touch device but was still
   getting 17px topbar links. Mouse users keep the compact spacing. */
@media (max-width:860px), (pointer:coarse){
  .topbar .wrap{ padding-top:6px; padding-bottom:6px; }
  .topbar a{ display:inline-block; padding:6px 0; }
  .footer-nav{ gap:2px 18px; }
  .footer-nav a{ display:inline-block; padding:9px 0; }
  .footer-brand{ padding:4px 0; }
  /* Standalone links that form their own line (card "read more", contact
     phone/email, footer detail columns) rather than sitting mid-sentence. */
  .card p > a:only-child,
  .contact-grid a,
  .footer-cols a,
  .cat-cta a{ display:inline-block; padding:6px 0; }

  /* These links sit mid-sentence beside other text, so the padding used
     elsewhere inflated them (32px against a neighbouring 20px) and knocked
     them off the shared baseline. Instead raise the line-height of the whole
     line and make the link inline-block: an inline element's hit box is only
     its font content area and ignores line-height, but an inline-block adopts
     it — clearing 24px while every item keeps the same baseline. */
  .footer-fine{ line-height:1.95; }
  .contact-lines{ line-height:1.75; }
  .footer-fine a,
  .contact-lines a{ display:inline-block; }
}

/* ---------- Contact strip ---------- */
.contact-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:24px; }
@media (max-width:780px){ .contact-grid{ grid-template-columns:1fr; } }
.contact-grid h3{ font-size:.85rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft); margin-bottom:10px; }
.contact-grid p{ margin:0; font-size:.95rem; }

/* ---------- Footer ---------- */
footer.site{
  background:var(--paper-raised);
  border-top:1px solid var(--line);
  padding:40px 0 28px;
  margin-top:24px;
}
/* Below this width the footer content runs close enough to the viewport edge
   that the fixed back-to-top button lands on top of the last row — it was
   covering the "Website by Cambi Growth" credit on tablets. Reserve the
   button's footprint so nothing sits under it. Wider viewports centre the
   content well clear of the button and need no reservation. */
@media (max-width:1240px){
  footer.site{ padding-bottom:86px; }
}
.footer-top{
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:28px;
  padding-bottom:24px; border-bottom:1px solid var(--line); margin-bottom:20px;
}
.footer-brand{ display:flex; gap:10px; align-items:center; }
.footer-brand svg, .footer-brand img{ width:30px; height:30px; object-fit:contain; }
.footer-nav{ display:flex; flex-wrap:wrap; gap:6px 18px; font-size:.86rem; }
.footer-nav a{ color:var(--ink-soft); text-decoration:none; }
.footer-nav a:hover{ color:var(--ink); }
/* Footer detail columns — hours, contact and coverage are the things people
   scroll to the bottom looking for, and they carry local-SEO weight too. */
.footer-cols{
  display:grid; grid-template-columns:repeat(3,1fr); gap:24px;
  padding-bottom:22px; margin-bottom:18px;
  border-bottom:1px solid var(--line);
}
@media (max-width:720px){ .footer-cols{ grid-template-columns:1fr; gap:18px; } }
.footer-cols .col-label{
  display:block; font-size:.68rem; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-soft); margin-bottom:8px;
}
.footer-cols p{ margin:0; font-size:.86rem; line-height:1.65; }
.footer-cols a{ text-decoration:none; }
.footer-cols a:hover{ text-decoration:underline; }
.footer-cols ul{
  margin:0; padding:0; list-style:none;
  font-size:.86rem; line-height:1.65; color:var(--ink-soft);
}

.footer-fine{
  display:flex; flex-wrap:wrap; justify-content:space-between;
  align-items:baseline; gap:10px;
  font-size:.8rem; color:var(--ink-soft);
}
/* Copyright + build credit travel together on the right, mirroring the
   grouped bottom row used on the AAFARMA site. Baseline alignment keeps the
   credit sitting on the same line as the text beside it. */
.footer-credit{ display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 22px; }

/* ---------- Utility ---------- */
.center{ text-align:center; }
.mt-0{ margin-top:0; }
