/* Imihanda - global stylesheet (the site was called Rwandan Pages when this file began, then Signpost until 30 Sep 2026).
   PALETTE: the Rwandan flag colours plus neutrals -
   flag blue #00A1DE, with darker shades of the same hue for text and fills (--green, --green-deep,
   --green-ink); flag yellow #FAD201 (--amber), with --star and --amber-ink for small marks on
   white; flag green #20603D (--rw-green) for WhatsApp. The only colours outside the flag are the
   two status tokens --danger and --ok. Greys (--body, --faint, --line, --paper) are near-neutral.
   The blue tokens are named --green/--mint for historical reasons; renaming them would touch
   every rule for no visual change. Use a token for any new colour, not a raw hex value. */
:root{
  /* ---- Spacing scale (30 Jul 2026) ----
     A 2px scale, not a 4px grid. The site already used even spacing almost everywhere; the odd
     values (3, 5, 7, 9, 11, 13, 15, 21) were the arbitrary ones and are snapped to their even
     neighbour, a shift of at most 1px. A true 4px grid would have moved ~200 declarations by up to
     3px each - a redesign of every component, not a consistency fix, and unverifiable across
     12,736 live pages. Use these tokens for NEW spacing. */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px;
  --sp-6:24px; --sp-8:32px; --sp-10:40px; --sp-12:48px;

  /* ---- Type scale (30 Jul 2026) ----
     Replaces 25 hand-typed sizes, 8 of them half-pixel (14.5, 13.5, 15.5, 12.5, 16.5, 17.5, 11.5,
     10.5), with 10 steps. Half-pixel values rounded UP so nothing text-bearing lands under 12px.
     --fs-base is 14px, not 16px: this is a dense directory and 14px is what Yelp sets its listing
     body at. Page prose uses --fs-lg (16px). */
  --fs-xs:12px; --fs-sm:13px; --fs-base:14px; --fs-md:15px; --fs-lg:16px;
  --fs-xl:18px; --fs-2xl:21px; --fs-3xl:24px; --fs-4xl:30px; --fs-5xl:40px;
  /* The four fluid heading sizes (28 Sep 2026; DESIGN.md "The Four Clamps Rule"). Every heading
     above 21px uses one of these; they replaced 11 hand-set clamps. */
  --fs-hero:clamp(26px,3.4vw,44px); --fs-display:clamp(26px,4vw,38px);
  --fs-headline:clamp(24px,3.2vw,32px); --fs-subhead:clamp(19px,2.4vw,23px);
  /* 9 line-heights collapsed to 3 roles. Body sits at 1.5 (readability floor). */
  --lh-tight:1.15; --lh-snug:1.3; --lh-body:1.5;

  --green:#0077B3; --green-deep:#005587; --green-ink:#0A2E44; --flag-blue:#00A1DE;
  --mint:#E5F5FC; --mint-2:#C9EBF8; --on-mint:#005587;
  --amber:#FAD201; --amber-soft:#FDF6D8; --star:#DFA900; --on-amber:#231A02;
  --amber-deep:#E9C400; --amber-edge:#EBD9A6;
  /* Readable-on-white version of the brand yellow, same pattern as --green-ink for --green.
     The raw --amber is 1.47:1 against a white card (fails even the 3:1 non-text floor) - far too
     faint for a small tick icon. --amber-ink is a darker gold at 5.81:1, still unmistakably
     "yellow", legible at 16px. */
  --amber-ink:#7A6300;
  --rw-green:#20603D; --rw-green-soft:#E7F1EB; --rw-green-soft-2:#D7E9DE; --on-rw-green:#17452C;
  --ink:#111111; --body:#333A3E; --faint:#666B6E;
  --paper:#F6F8FA; --card:#FFFFFF; --line:#E4E6E8;
  /* Rating tiles: empty, and empty on a listing with no reviews yet (also the skeleton grey). */
  --tile-empty:#C8D0D6; --tile-none:#E9EDF0;
  /* Navy-tinted backs for controls that sit on photographs. */
  --scrim:rgba(8,24,36,.42); --scrim-strong:rgba(8,24,36,.72);
  /* Status colours: the two deliberate exceptions to the flag palette. Red marks closed and
     unclaimed listings and invalid fields; green marks a valid field. The inline SVG ticks in the
     form styles repeat these as %23C0392B / %231F9D55, since a data URI cannot read a variable. */
  --danger:#C0392B; --ok:#1F9D55;
  --hero-ink:#FFFFFF; --hero-dim:#B5E2F5;
  --shadow:0 1px 2px rgba(10,46,68,.06),0 8px 24px rgba(10,46,68,.07);
  --shadow-float:0 18px 44px rgba(10,46,68,.16);   /* dropdowns, mega panels, suggestion lists */
  /* Corner scale (28 Sep 2026). Replaced 14 hand-typed radii; 5, 9 and 18px snapped to their
     neighbours (a shift of 1-2px). --r stays the card radius. Circles use 50%, not a token. */
  --r-xs:4px; --r-sm:6px; --r-row:8px; --r-ctl:10px; --r-panel:12px; --r:14px;
  --r-lg:16px; --r-band:20px; --r-footer:26px; --r-pill:99px;
  /* cards lift on hover and dip on press: only these properties ever change */
  --tr-card:border-color .2s, box-shadow .2s, transform .2s, opacity .2s;
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  /* Yelp's interface is set in Proxima Nova, which is a commercial licence we do not hold.
     Figtree is the closest free equivalent (same geometric-humanist skeleton, near-identical
     x-height and letterforms) and is on Google Fonts. The fallback chain below is Yelp's own
     (Helvetica Neue, Arial), so the site degrades to what yelp.com degrades to. */
  font-family:'Figtree',-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Helvetica,Arial,sans-serif;
  background:var(--paper); color:var(--body);
  font-size:var(--fs-lg); line-height:var(--lh-body);
}
h1,h2,h3,h4{color:var(--ink); font-weight:750; letter-spacing:-.02em; line-height:var(--lh-tight); text-wrap:balance}
a{color:inherit; text-decoration:none}
button{font:inherit; cursor:pointer; border:0}
svg{display:block; flex:none}
img{max-width:100%; display:block}
.wrap{max-width:1400px; margin:0 auto; padding:0 20px}

/* Keyboard focus. One ring in the brand blue (4.9:1 on white) instead of each browser's default;
   amber on the blue surfaces, where blue would vanish. Inputs keep their own focus styles. */
:focus-visible{outline:2px solid var(--green); outline-offset:2px}
.ftr-card :focus-visible, .cta :focus-visible,
.hslides :focus-visible, .pop-card .bd :focus-visible{outline-color:var(--amber)}
@media(max-width:760px){.hdr :focus-visible{outline-color:var(--amber)}}
#main:focus{outline:none}
/* the skip link lands here: clear the sticky header (64px desktop, taller on phones) */
#main{scroll-margin-top:72px}
@media(max-width:760px){#main{scroll-margin-top:130px}}
.skip{
  position:absolute; left:12px; top:-60px; z-index:100; padding:10px 16px; border-radius:var(--r-ctl);
  background:var(--ink); color:#fff; font-size:var(--fs-base); font-weight:700;
}
.skip:focus{top:12px}
.sr-only{position:absolute; width:1px; height:1px; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0}

/* header */
.hdr{background:var(--card); border-bottom:1px solid var(--line); position:sticky; top:0; z-index:40}
.hdr .wrap{display:flex; align-items:center; gap:22px; height:64px}
.logo{display:flex; align-items:baseline; gap:0; font-size:var(--fs-3xl); font-weight:800; letter-spacing:-.03em; color:var(--ink)}
.logo i{width:9px; height:9px; border-radius:50%; background:var(--amber); display:inline-block; transform:translateY(-1px); margin-left:2px}
.logo > span:first-child{color:var(--green)}
.logo .lg2{color:var(--rw-green); font-weight:800}
.logo small{font-size:var(--fs-xs); font-weight:600; color:var(--faint); letter-spacing:.08em; margin-left:8px; text-transform:uppercase}
.nav{display:flex; gap:22px; font-size:var(--fs-base); font-weight:600; color:var(--body); margin-left:auto}
.nav a:hover{color:var(--green)}
.btn{
  display:inline-flex; align-items:center; gap:8px; justify-content:center;
  background:var(--green); color:#fff; font-weight:700; font-size:var(--fs-base);
  padding:12px 20px; border-radius:var(--r-ctl); transition:background .2s; cursor:pointer;
}
.btn:hover{background:var(--green-deep)}
.btn--ghost{background:transparent; color:var(--ink); border:1.5px solid var(--line)}
.btn--ghost:hover{background:var(--mint); border-color:var(--mint-2); color:var(--on-mint)}
.btn--amber{background:var(--amber); color:var(--on-amber)}
.btn--amber:hover{background:var(--amber-deep)}
.hdr .btn{padding:10px 16px}
.lang{display:flex; gap:2px; font-size:var(--fs-sm); font-weight:700; border:1.5px solid var(--line); border-radius:var(--r-row); padding:4px}
.lang a{padding:4px 8px; border-radius:var(--r-sm); color:var(--faint)}
.lang a.on{background:var(--mint); color:var(--on-mint)}
@media(max-width:820px){.nav{display:none}}
@media(max-width:640px){
  .logo small{display:none}
  .logo{font-size:var(--fs-2xl)}
  .hdr .wrap{justify-content:space-between; gap:8px}
  .hdr .btn{margin-left:auto; font-size:var(--fs-sm); padding:8px 12px; white-space:nowrap}
  .lang{font-size:var(--fs-xs)}
  .lang a{padding:2px 6px}
}

/* search suggestions */
.sugg{
  position:absolute; top:calc(100% + 8px); left:0; right:0; z-index:30;
  background:var(--card); border-radius:var(--r-panel); box-shadow:var(--shadow-float);
  overflow:hidden; text-align:left; display:none;
}
.sugg.open{display:block}
.sugg a{display:flex; align-items:center; gap:10px; padding:12px 16px; font-size:var(--fs-base); color:var(--ink); border-bottom:1px solid var(--line)}
.sugg a:last-child{border-bottom:0}
.sugg a:hover{background:var(--paper)}
/* the arrow-key row: the pale hover tint alone is barely visible against white, invisible as a keyboard cursor */
.sugg a.sel{background:var(--mint); box-shadow:inset 0 0 0 2px var(--green)}
.sugg a b{font-weight:700}
.sugg a span{color:var(--faint); font-size:var(--fs-sm); margin-left:auto; white-space:nowrap}

/* Justdial-style hero */
.jd-hero{padding:24px 0 6px}
/* stats */
.stats{border-bottom:1px solid var(--line); background:var(--card)}
.stats .wrap{display:grid; grid-template-columns:repeat(4,1fr); gap:12px; padding:22px 20px}
.stat{text-align:center}
.stat b{display:block; font-size:var(--fs-3xl); font-weight:800; color:var(--ink); letter-spacing:-.02em; font-variant-numeric:tabular-nums}
.stat span{font-size:var(--fs-sm); font-weight:600; color:var(--faint)}   /* sentence case: the /business/ labels run to 37 characters, too long to read in capitals */
@media(max-width:640px){.stats .wrap{grid-template-columns:repeat(2,1fr); gap:18px 12px}}

/* sections */
.sec{padding:56px 0}
.sec--mid{padding:30px 0} /* content sits centered between section divider lines */
.sec-head{display:flex; align-items:flex-end; justify-content:space-between; gap:16px; margin-bottom:26px}
.sec-head h2{font-size:var(--fs-headline)}
.sec-head p{color:var(--faint); font-size:var(--fs-md); margin-top:6px}
.sec-head .more{font-size:var(--fs-base); font-weight:700; color:var(--green); white-space:nowrap; display:flex; align-items:center; gap:6px}
.sec-head .more:hover{color:var(--on-mint)}

/* category tiles */
.cats{display:grid; grid-template-columns:repeat(6,1fr); gap:12px}
@media(max-width:960px){.cats{grid-template-columns:repeat(4,1fr)}}
@media(max-width:640px){.cats{grid-template-columns:repeat(2,1fr)}}
.cat{
  background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  padding:18px 14px; text-align:center; transition:var(--tr-card); display:block;
}
.cat .ic{
  width:44px; height:44px; margin:0 auto 10px; border-radius:var(--r-panel);
  background:var(--mint); color:var(--green); display:flex; align-items:center; justify-content:center;
}
.cat b{display:block; font-size:var(--fs-base); font-weight:700; color:var(--ink); line-height:var(--lh-snug)}
.cat span{font-size:var(--fs-xs); color:var(--faint); font-variant-numeric:tabular-nums}

/* photo cards */
.pcards{display:grid; grid-template-columns:repeat(3,1fr); gap:18px}
@media(max-width:960px){.pcards{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.pcards{grid-template-columns:1fr}}
.pcard{
  background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:var(--tr-card); display:flex; flex-direction:column;
}
.pcard .ph{position:relative; height:180px; overflow:hidden; background:var(--mint)}
.pcard .ph img{width:100%; height:100%; object-fit:cover; transition:transform .35s}
.pcard .ph .tag{position:absolute; top:12px; left:12px; z-index:1}
.pcard .ph .ph-ini{
  width:100%; height:100%; display:flex; align-items:center; justify-content:center;
  font-size:var(--fs-5xl); font-weight:800; color:var(--green); opacity:.55; letter-spacing:-.03em;
}
.pcard .bd{padding:16px 18px 18px; display:flex; flex-direction:column; gap:8px; flex:1}
.pcard .bd .nm{display:flex; align-items:center; gap:6px; font-size:var(--fs-lg); color:var(--ink); font-weight:750; letter-spacing:-.01em}
.pcard .bd .sub{font-size:var(--fs-sm); color:var(--faint)}
.vrf{display:inline-flex; align-items:center; gap:4px; color:var(--rw-green); flex:none}
.stars{display:flex; align-items:center; gap:8px; font-size:var(--fs-sm)}
/* Star tiles, per the reference: rounded squares holding a white star, filled to the nearest half.
   Blue is the brand primary (#0077B3) - white star on it measures 4.90:1, above the 4.5 text floor.
   The EMPTY tile is 1.56:1 against a white card, which does not meet WCAG 1.4.11's 3:1 for non-text
   contrast. That is acceptable here only because the numeric rating and review count are always
   rendered as text beside the tiles, so the score never depends on reading the tiles - but it is a
   known compromise, not a pass. It is already darker than the reference's near-white tiles. */
.stars .st{display:inline-flex; gap:2px; letter-spacing:0}
.stars .sq{
  width:18px; height:18px; border-radius:var(--r-xs); flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:11px; line-height:1; color:#fff; font-style:normal;
}
.stars .sq.on{background:var(--green)}
.stars .sq.off{background:var(--tile-empty)}
.stars .sq.half{background:linear-gradient(90deg,var(--green) 50%,var(--tile-empty) 50%)}
.stars b{color:var(--ink); font-weight:750; font-variant-numeric:tabular-nums}
.stars span{color:var(--faint)}
.foot{display:flex; gap:8px; margin-top:auto; padding-top:8px}
.chip-btn{
  flex:1; display:flex; align-items:center; justify-content:center; gap:8px;
  font-size:var(--fs-sm); font-weight:700; padding:10px 10px; border-radius:var(--r-ctl);
  background:var(--rw-green-soft); color:var(--on-rw-green); transition:background .2s;
}
.chip-btn:hover{background:var(--rw-green-soft-2)}
.chip-btn--solid{background:var(--green); color:#fff}
.chip-btn--solid:hover{background:var(--green-deep)}
.tag{font-size:var(--fs-xs); font-weight:700; letter-spacing:.06em; text-transform:uppercase; padding:4px 10px; border-radius:var(--r-sm); background:var(--amber); color:var(--on-amber)}
.hint{font-size:var(--fs-xs); color:var(--faint); text-align:center; margin-top:14px}

/* bento hero */
.bento{display:grid; grid-template-columns:1.05fr 1fr; grid-template-rows:auto auto; gap:14px}
@media(max-width:860px){.bento{grid-template-columns:1fr}}
.bt{border-radius:var(--r-lg); overflow:hidden; position:relative}
.bt-state{background:var(--mint); padding:30px 32px; display:flex; flex-direction:column; min-height:300px}
.bt-state h1,.bt-state h2{font-size:var(--fs-hero); font-weight:800; letter-spacing:-.025em; max-width:16ch}
.bt-state .arrow{position:absolute; top:18px; right:18px; width:40px; height:40px; border-radius:var(--r-panel); background:var(--card); color:var(--ink); display:flex; align-items:center; justify-content:center; box-shadow:var(--shadow)}
.bt-state .stat{margin-top:auto; font-size:var(--fs-base); color:var(--body); max-width:40ch; padding-top:26px}
.bt-photo-pair{display:grid; grid-template-columns:1fr 1fr; gap:14px}
.bt-mini{position:relative; border-radius:var(--r-lg); overflow:hidden; min-height:210px; display:block}
.bt-mini img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; transition:transform .35s}
.bt-mini b{position:absolute; left:16px; bottom:13px; z-index:2; color:#fff; font-size:var(--fs-md); font-weight:750; letter-spacing:-.01em}
.bt-mini::after{content:""; position:absolute; inset:50% 0 0 0; background:linear-gradient(transparent, rgba(5,20,32,.62))}
.bt-tall{grid-column:2; grid-row:1/3; min-height:520px; display:block}
@media(max-width:860px){.bt-tall{grid-column:auto; grid-row:auto; min-height:420px}}
.bt-tall img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0}
/* Caption scrim. It used to fade straight from .72 to clear across the top 45% of the card, so by
   the caption's second line it was thin: measured 28 Sep 2026, the business-cards slide fell to
   3.87:1 behind the text. Holding .62 through 110px keeps white 16px text above 5:1 even over a
   pure-white photo, whatever image is swapped in; the fade starts below the caption. */
.hsl::before{content:""; position:absolute; inset:0 0 55% 0; background:linear-gradient(rgba(5,20,32,.72), rgba(5,20,32,.62) 110px, transparent); z-index:1}
.bt-tall p{position:absolute; top:22px; left:24px; right:24px; z-index:2; color:#fff; font-size:var(--fs-lg); font-weight:650; line-height:var(--lh-body); max-width:42ch}
.bt-tall .btns{position:absolute; right:18px; bottom:18px; z-index:2; display:flex; gap:10px}
.bt-tall .btn--white{background:#fff; color:var(--ink)}

/* for-business landing */
.bizhero{background:var(--mint); border-bottom:1px solid var(--line); text-align:center; padding:52px 0 56px}
.bizhero h1{font-size:var(--fs-hero); margin-bottom:12px}
.bizhero .lead{font-size:var(--fs-lg); max-width:56ch; margin:0 auto 22px}
.bsearch{
  position:relative; max-width:540px; margin:0 auto 18px; text-align:left;
  display:flex; align-items:center; gap:10px; height:54px; padding:0 16px;
  background:var(--card); border:1.5px solid var(--line); border-radius:var(--r-panel);
}
.bsearch:focus-within{border-color:var(--green)}
.bsearch > svg{color:var(--green); flex:none}
.bsearch input{flex:1; min-width:0; border:0; outline:0; font:inherit; font-size:var(--fs-lg); font-weight:600; color:var(--ink); background:transparent}
.bsearch input::placeholder{color:var(--faint); font-weight:500}
.bsearch .sugg{top:calc(100% + 8px); border:1px solid var(--line); box-shadow:var(--shadow-float)}
.stats--3 .wrap{grid-template-columns:repeat(3,1fr)}
.sec-head--c{justify-content:center; text-align:center}
.sec-head--c p{max-width:60ch; margin-inline:auto}
.bz2{display:grid; grid-template-columns:1.05fr 1fr; gap:30px; align-items:center}
@media(max-width:820px){.bz2{grid-template-columns:1fr}}
.bz2 h2{font-size:var(--fs-headline); margin-bottom:10px}
.bz2 > div > p{font-size:var(--fs-md); max-width:52ch}
.bz-btns{display:flex; gap:10px; margin-top:18px; flex-wrap:wrap}
.bz-list{list-style:none; display:flex; flex-direction:column; gap:14px}
.bz-list li{display:flex; gap:12px; align-items:center; font-size:var(--fs-md); font-weight:650; color:var(--ink)}
.bz-list svg{color:var(--rw-green); flex:none}
.bz-steps{display:flex; flex-direction:column; gap:18px}
.bz-step{display:flex; gap:14px; align-items:flex-start}
.bz-step > b{flex:none; width:32px; height:32px; border-radius:50%; background:var(--amber); color:var(--on-amber); display:flex; align-items:center; justify-content:center; font-size:var(--fs-md)}
.bz-step h3{font-size:var(--fs-lg); margin-bottom:2px}
.bz-step p{font-size:var(--fs-base)}

/* start-a-project ideas page (Yelp projects style) */
.sp-top{padding-top:36px; padding-bottom:4px}
.sp-top h1{font-size:var(--fs-display); margin-bottom:4px}
.sp-sub{font-size:var(--fs-lg); color:var(--faint); margin-bottom:18px}
.spchips{display:flex; flex-wrap:wrap; gap:10px}
.spchip{
  display:inline-flex; align-items:center; gap:10px; padding:10px 16px; border-radius:var(--r-pill);
  background:var(--card); border:1.5px solid var(--line);
  font-size:var(--fs-base); font-weight:650; color:var(--ink);
  transition:background .18s, border-color .18s, color .18s;
}
.spchip svg{color:var(--green); width:17px; height:17px}
.spchip:hover{background:var(--mint); border-color:var(--mint-2); color:var(--on-mint)}
.sp-sec{padding:26px 0 4px}
.sp-sec h2{font-size:var(--fs-headline); margin-bottom:16px}
.ideas{display:grid; grid-template-columns:repeat(3,1fr); gap:14px}
@media(max-width:820px){.ideas{grid-template-columns:1fr 1fr}}
.idea{
  display:block; background:var(--card); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden; transition:box-shadow .2s, transform .2s;
}
.idea .ph{display:block; aspect-ratio:16/10; overflow:hidden}
.idea .ph img{width:100%; height:100%; object-fit:cover; display:block; transition:transform .3s}
.idea .bd{display:block; padding:12px 14px 14px}
.idea .bd b{display:block; font-size:var(--fs-md); color:var(--ink); margin-bottom:4px}
.idea .go{display:inline-flex; align-items:center; gap:6px; font-size:var(--fs-sm); font-weight:700; color:var(--green)}
.sp-form{max-width:640px; margin:0 auto}
.sp-form h2{font-size:var(--fs-2xl); margin-bottom:4px}

/* unclaimed listings */
.badge--uc{background:var(--paper); color:var(--faint); border:1px solid var(--line)}
.stars--none{color:var(--faint); font-size:var(--fs-sm); font-weight:600}
.stars--none .sq.off{background:var(--tile-none)}   /* lighter than the rated empty tile: reads as "not yet", not "scored zero" */
.uclaim{
  display:flex; gap:14px; align-items:center; flex-wrap:wrap;
  background:var(--amber-soft); border:1px solid var(--amber-edge); border-radius:var(--r);
  padding:14px 18px; margin-top:16px;
}
.uclaim > svg{color:var(--ink); flex:none; width:22px; height:22px}
.uclaim > div{flex:1; min-width:220px}
.uclaim b{display:block; font-size:var(--fs-md); color:var(--ink)}
.uclaim p{font-size:var(--fs-sm); margin:2px 0 0}

/* review sign-in gate */
.rev-lock{display:flex; gap:14px; align-items:flex-start; background:var(--mint); border-radius:var(--r-panel); padding:16px 18px; margin-top:14px}
.rev-lock[hidden]{display:none}
.rev-lock svg{color:var(--green); flex:none; margin-top:2px}
.rev-lock b{display:block; font-size:var(--fs-md); color:var(--ink); margin-bottom:4px}
.rev-lock p{font-size:var(--fs-base); margin-bottom:12px}
.rev-who{font-size:var(--fs-sm); color:var(--faint); margin-top:8px}
.rev-who b{color:var(--body)}

/* business page action row - Yelp-style icon stack: review / call / whatsapp / directions / website.
   Each item renders only when the listing really has that contact (never a dead button). */
.pacts{display:flex; justify-content:space-around; align-items:flex-start; gap:6px; margin:18px 0 0; padding:14px 2px; border-top:1px solid var(--line); border-bottom:1px solid var(--line)}
.pact{
  display:flex; flex-direction:column; align-items:center; gap:9px; cursor:pointer;
  background:none; border:0; padding:0; font:inherit; font-size:var(--fs-sm); font-weight:650;
  color:var(--body); flex:1; min-width:0; text-align:center;
}
.pact .pact-ic{
  width:40px; height:40px; border:1.5px solid var(--line); border-radius:var(--r-panel); flex:none;
  display:flex; align-items:center; justify-content:center; color:var(--ink);
  transition:background .18s, border-color .18s;
}
.pact .pact-ic svg{width:20px; height:20px}
.pact > span{max-width:100%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.pact:hover .pact-ic{background:var(--mint); border-color:var(--mint-2)}
.prec{
  display:flex; align-items:center; flex-wrap:wrap; gap:12px 16px;
  margin-top:16px;
}
.prec b{font-size:var(--fs-md); color:var(--ink)}
.prec span{display:flex; gap:10px}
.prec button{
  background:var(--card); border:1.5px solid var(--line); color:var(--body);
  font:inherit; font-size:var(--fs-base); font-weight:650; padding:10px 22px; border-radius:var(--r-pill);
  transition:background .18s, border-color .18s, color .18s;
}
.prec button:hover{background:var(--mint); border-color:var(--mint-2); color:var(--on-mint)}
#savedlist a{display:flex; align-items:center; justify-content:space-between; gap:12px}
#savedlist .sv-x{
  flex:none; font:inherit; font-size:var(--fs-sm); font-weight:700; color:var(--faint);
  background:none; border:0; padding:4px 6px; cursor:pointer;
}
#savedlist .sv-x:hover{color:var(--ink)}
@media(max-width:640px){
  .prec{flex-direction:column; align-items:flex-start; gap:10px}
}

/* hero photo slideshow: cross-fade + slow drift, with vertical progress bars.
   NOTE: .hsl - NOT .hs, which is the header search bar. */
.hsl{position:absolute; inset:0; display:block; opacity:0; visibility:hidden; transition:opacity .8s ease, visibility 0s linear .8s}
.hsl.on{opacity:1; visibility:visible; z-index:2; transition:opacity .8s ease, visibility 0s linear 0s}
.hsl-copy{
  position:absolute; left:58px; right:24px; top:22px; z-index:2;
  display:flex; flex-direction:column; align-items:flex-start; gap:16px;
}
.hslides .hsl-copy p{position:static; left:auto; right:auto; top:auto}
/* Yelp-style search pill under the caption */
.hsl-find{
  padding:12px 22px 12px 18px; border-radius:var(--r-pill); font-size:var(--fs-md); font-weight:800;
  /* solid white stroke, no shadow (owner's call) */
  box-shadow:0 0 0 2px #fff;
}
.hsl-find svg{width:18px; height:18px}
@keyframes hslDrift{from{transform:scale(1.02) translate3d(0,0,0)} to{transform:scale(1.11) translate3d(-1.4%,-1.2%,0)}}
.hsl.on img{animation:hslDrift 9s ease-out both}
.hsl-ui{
  position:absolute; left:16px; top:22px; z-index:5;
  height:min(330px,56%); display:flex; flex-direction:column; align-items:center; gap:14px;
}
.hsl-bars{flex:1; width:18px; display:flex; flex-direction:column; gap:10px}
.hsl-bar{position:relative; flex:1; width:18px; padding:0; background:none; border:0; cursor:pointer}
.hsl-bar::before{
  content:""; position:absolute; left:50%; top:0; bottom:0; width:3px;
  transform:translateX(-50%); background:rgba(255,255,255,.45); border-radius:var(--r-pill);
}
.hsl-bar i{
  position:absolute; left:50%; top:0; width:3px; height:0;
  transform:translateX(-50%); background:#fff; border-radius:var(--r-pill);
}
@keyframes hslFill{from{height:0} to{height:100%}}
.hsl-bar.on i{animation:hslFill 9s linear both}
.hsl-play{
  flex:none; width:26px; height:26px; border-radius:50%;
  background:var(--scrim); color:#fff; display:flex; align-items:center; justify-content:center;
  transition:background .2s;
}
.hsl-play:hover{background:var(--scrim-strong)}
.hslides.paused .hsl.on img,.hslides.paused .hsl-bar.on i{animation-play-state:paused}
@media(max-width:860px){
  .hsl-ui{height:min(210px,44%); left:13px; top:18px}
  .hsl-copy{left:50px; right:18px; gap:14px}
  .hsl-find{padding:12px 18px 12px 16px; font-size:var(--fs-base)}
}
@media(prefers-reduced-motion:reduce){
  .hsl{transition:none}
  .hsl.on img{animation:none}
  .hsl-bar.on i{animation:none; height:100%}
}
.bt-tall .btn--white:hover{background:var(--mint)}

/* popular enquiry cards */
.pop-cards{display:grid; grid-template-columns:repeat(4,1fr); gap:16px}
@media(max-width:960px){.pop-cards{grid-template-columns:repeat(2,1fr)}}
.pop-card{border-radius:var(--r); overflow:hidden; border:1px solid var(--line); background:var(--card); transition:var(--tr-card); display:flex; flex-direction:column}
.pop-card .ph{height:170px; position:relative}
@media(max-width:640px){.pop-card .ph{height:120px}}
.pop-card .ph img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover}
.pop-card .bd{background:var(--green); color:#fff; padding:14px 16px 16px; display:flex; flex-direction:column; gap:10px; flex:1}
.pop-card .bd b{font-size:var(--fs-md); font-weight:750; letter-spacing:-.01em}
.pop-card .bd .enq{align-self:flex-start; font-size:var(--fs-sm); font-weight:700; border:1.5px solid rgba(255,255,255,.85); color:#fff; padding:8px 14px; border-radius:var(--r-row); transition:background .2s}
.pop-card:hover .bd .enq{background:rgba(255,255,255,.15)}

/* explore places */
/* minmax(0,1fr) not plain 1fr: a 1fr track cannot shrink below its content's min-width, which
   is half of why this row used to push the PAGE sideways. The other half was the wrapper span
   below. Keep both fixes together. */
.explore-grid{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px}
@media(max-width:960px){.explore-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:520px){.explore-grid{grid-template-columns:minmax(0,1fr)}}
.exp-card{display:flex; align-items:center; gap:14px; background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:12px; transition:var(--tr-card)}
.exp-card:hover{box-shadow:var(--shadow); border-color:var(--mint-2)}
.exp-card img{width:96px; height:76px; object-fit:cover; border-radius:var(--r-ctl); flex:none}
.exp-card b{display:block; font-size:var(--fs-md); color:var(--ink); font-weight:750; line-height:var(--lh-tight); margin-bottom:2px}
.exp-card em{display:block; font-style:normal; font-size:var(--fs-xs); color:var(--faint); margin-bottom:4px}
/* The wrapper span must STACK title/subtitle/link. `.exp-card span` used to match the wrapper
   too, making it an inline-flex ROW - title, subtitle and "Explore" sat side by side and the
   row overflowed the viewport. Scope the link style to the nested span with a child selector. */
.exp-card > span{display:flex; flex-direction:column; min-width:0}
.exp-card > span > span{font-size:var(--fs-sm); color:var(--green); font-weight:700; display:inline-flex; align-items:center; gap:4px; align-self:flex-start}
.newtag{font-size:var(--fs-xs); font-weight:800; letter-spacing:.08em; text-transform:uppercase; background:var(--amber); color:var(--on-amber); border-radius:var(--r-sm); padding:4px 8px; vertical-align:middle; margin-left:8px; display:inline-block; transform:translateY(-3px)}

/* travel panel */
.trav{display:flex; gap:30px; align-items:center; background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:28px}
@media(max-width:820px){.trav{flex-direction:column; align-items:flex-start; gap:18px}}
.trav .tx{max-width:320px}
.trav .tx h2{font-size:var(--fs-2xl); margin-bottom:8px}
.trav .tx p{font-size:var(--fs-base)}
.trav .tiles{display:flex; gap:16px 6px; flex-wrap:wrap; flex:1; justify-content:space-around}
.trav .tile{display:flex; flex-direction:column; align-items:center; gap:8px; text-align:center; width:min(112px, calc((100% - 24px) / 5))}
.trav .tile .ic{width:60px; height:60px; border-radius:var(--r-lg); border:1px solid var(--line); background:var(--paper); color:var(--green); display:flex; align-items:center; justify-content:center; transition:background .2s, border-color .2s}
.trav .tile:hover .ic{background:var(--mint); border-color:var(--mint-2)}
.trav .tile b{font-size:var(--fs-sm); color:var(--ink); line-height:var(--lh-tight)}
.trav .tile span{font-size:var(--fs-xs); color:var(--rw-green); font-weight:650; line-height:var(--lh-tight)}
/* The five tiles never leave a lone one on the last row (owner's call, 28 Sep 2026). With fixed
   112px tiles they stacked five deep at 320px and wrapped 2+2+1, 4+1 or 3+2 depending on width.
   Now: one row of five wherever a fifth of the space fits the longest word ("organisateurs",
   75px), capped at the old 112px; otherwise three across in two rows (3 + 2, second row
   centred) - phones, and 821-960px where the tiles share the card with the text column. Phone
   side padding drops to 16px so a third of the card still fits that word at 320px. */
@media(max-width:640px), (min-width:821px) and (max-width:960px){
  .trav .tiles{justify-content:center}
  .trav .tile{width:calc((100% - 12px) / 3)}
}
@media(max-width:640px){.trav{padding:20px 16px}}

/* quad panels */
.quad{display:grid; grid-template-columns:1fr 1fr; gap:16px}
@media(max-width:960px){.quad{grid-template-columns:1fr}}
.quad .qp{background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:22px}
.quad .qp h3{font-size:var(--fs-xl); margin-bottom:14px}
.quad .qtiles{display:grid; grid-template-columns:repeat(3,1fr); gap:12px}
.qtile{display:block}
.qtile .ph{display:block; height:110px; border-radius:var(--r-ctl); overflow:hidden; position:relative; margin-bottom:8px}
.qtile .ph img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; transition:transform .3s}
.qtile b{display:block; font-size:var(--fs-sm); color:var(--ink); font-weight:700; line-height:var(--lh-tight)}
.qtile:hover b{color:var(--green)}
@media(max-width:640px){.qtile .ph{height:86px}.qtile b{font-size:var(--fs-sm)}}

/* /business/ feature list (28 Sep 2026): replaced a band of identical icon-tile cards, which
   DESIGN.md rules out. Plain heading + text under a hairline; the page's numbered "How it works"
   steps stay the only numbered list, so these never read as steps. */
.bz-feats{list-style:none; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-8); max-width:1040px; margin:var(--sp-6) auto 0}
.bz-feats li{border-top:1px solid var(--line); padding-top:var(--sp-4)}
.bz-feats h3{font-size:var(--fs-lg); margin-bottom:var(--sp-1)}
.bz-feats p{font-size:var(--fs-base)}
@media(max-width:820px){.bz-feats{grid-template-columns:minmax(0,1fr); gap:var(--sp-5)}}

/* seo link mesh */
.seo{padding:50px 0; border-top:1px solid var(--line)}
.seo h2{font-size:var(--fs-2xl); margin-bottom:6px}
.seo > .wrap > p{font-size:var(--fs-base); color:var(--faint); margin-bottom:24px}
.seo-cols{display:grid; grid-template-columns:repeat(4,1fr); gap:26px}
@media(max-width:960px){.seo-cols{grid-template-columns:repeat(2,1fr)}}
.seo-cols b{display:block; font-size:var(--fs-sm); color:var(--ink); letter-spacing:.06em; text-transform:uppercase; margin-bottom:10px}
.seo-cols a{display:block; font-size:var(--fs-base); padding:4px 0; color:var(--body)}
.seo-cols a:hover{color:var(--green)}

/* CTA */
.cta-outer{max-width:1400px; margin:0 auto}
.cta{background:var(--green-deep); position:relative; overflow:hidden; border-radius:var(--r-band); margin:0 20px}
.cta .in{position:relative; padding:52px 30px; text-align:center}
.cta h2{color:var(--hero-ink); font-size:var(--fs-headline); margin-bottom:10px}
.cta p{color:var(--hero-dim); font-size:var(--fs-lg); max-width:480px; margin:0 auto 26px}

/* hero footer - rounded card with skyline band */
.ftr{margin:16px; color:var(--hero-dim); font-size:var(--fs-sm)}
@media(min-width:900px){.ftr{margin:20px}}
.ftr-card{position:relative; background:var(--green-deep); border-radius:var(--r-footer); overflow:hidden; max-width:1560px; margin:0 auto}
.ftr-hero{text-align:center; padding:48px 22px 34px; display:flex; flex-direction:column; align-items:center; gap:12px}
.ftr-hero .logo{font-size:var(--fs-3xl)}
.ftr-hero h2{color:#fff; font-size:var(--fs-headline); font-weight:800; letter-spacing:-.02em; max-width:22ch; text-wrap:balance}
.ftr-hero p{max-width:46ch; color:var(--hero-dim)}
.ftr-nl{display:flex; gap:10px; margin-top:8px; width:min(460px,100%)}
.ftr-nl input{flex:1; min-width:0; font:inherit; font-size:var(--fs-base); padding:12px 16px; border-radius:var(--r-ctl); border:0; outline:none; background:var(--card); color:var(--ink)}
.ftr-nl input:focus{box-shadow:0 0 0 3px rgba(250,210,1,.5)}
@media(max-width:520px){.ftr-nl{flex-direction:column}}
.ftr-nl-note{font-size:var(--fs-xs); color:var(--hero-dim)}
.ftr-cols-row{display:grid; grid-template-columns:repeat(4,1fr); gap:24px; padding-top:26px; padding-bottom:8px; border-top:1px solid rgba(255,255,255,.16)}
@media(max-width:760px){.ftr-cols-row{grid-template-columns:repeat(2,1fr)}}
.ftr b{display:block; color:#fff; font-size:var(--fs-sm); letter-spacing:.06em; text-transform:uppercase; margin-bottom:10px}
.ftr a{display:block; padding:4px 0; color:var(--hero-dim)}
.ftr a:hover{color:var(--amber)}
.ftr .ftr-line{display:block; padding:4px 0}
.ftr .logo > span:first-child{color:#fff}
.ftr .logo .lg2{color:var(--amber)}
.ftr .logo i{background:#fff}
.ftr-bottom{border-top:1px solid rgba(255,255,255,.16); margin-top:20px; padding-top:16px; padding-bottom:22px; font-size:var(--fs-sm); display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px}

/* breadcrumb + category page */
.crumb{font-size:var(--fs-sm); color:var(--faint); padding:18px 0 0}
.crumb a:hover{color:var(--green)}
.crumb i{margin:0 8px; font-style:normal; color:var(--line)}
.crumb .here{color:var(--ink); font-weight:600}
.cat-head{padding:16px 0 4px}
.cat-head h1{font-size:var(--fs-display); margin-bottom:8px}
.cat-head .meta{font-size:var(--fs-base); color:var(--faint)}
.cat-head .meta b{color:var(--green); font-weight:700}
/* Subcategory chips above the filter row: the on-page way to narrow a big category by TYPE
   (dentists inside clinics, lodges inside hotels). The header hover menu cannot do this job on
   mobile or for anyone arriving from Google. Counts are computed at build time by subCount(),
   from the same haystack app.js filters on, so the number always matches the result. */
/* Yelp-style subcategory row: round icon circles with the label underneath, one
   sideways-scrolling strip on every screen size (per the owner's reference, 30 Jul 2026). */
.subnav{display:flex; gap:16px; flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none;
        padding:14px 0 4px; scroll-snap-type:x proximity}
.subnav::-webkit-scrollbar{display:none}
.subnav a{
  flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:7px;
  min-width:0; padding:2px 0; scroll-snap-align:start;
  font-size:var(--fs-sm); font-weight:650; color:var(--body);
  text-decoration:none; transition:color .2s; text-align:center;
}
.subnav a .snc{
  display:flex; align-items:center; justify-content:center; width:48px; height:48px;
  border-radius:50%; background:var(--card); border:1.5px solid var(--line);
  color:var(--ink); transition:background .2s, border-color .2s, color .2s;
}
.subnav a .snc svg{width:20px; height:20px}
.subnav a:hover .snc{border-color:var(--green); color:var(--green)}
.subnav a.on{color:var(--green); font-weight:700}
.subnav a.on .snc{background:var(--green); border-color:var(--green); color:#fff}
@media(max-width:760px){
  /* full-bleed scroll on phones - the strip scrolls, the page never does */
  .subnav{margin:0 -18px; padding-left:18px; padding-right:18px; scroll-padding-left:18px}
}
.filters{display:flex; gap:8px; flex-wrap:wrap; padding:18px 0 8px}
.filters button{
  display:inline-flex; align-items:center; gap:6px;
  font-size:var(--fs-sm); font-weight:650; padding:8px 16px; border-radius:var(--r-pill);
  background:var(--card); color:var(--body); border:1.5px solid var(--line);
}
.filters button:hover{border-color:var(--mint-2); color:var(--ink)}
.filters button.on{background:var(--green); border-color:var(--green); color:#fff}
/* minmax(0,1fr), not 1fr: a 1fr track cannot shrink below its content's min-width, so between 960
   and ~1150px the list column held at 785px and pushed the page 123px sideways (found 28 Sep 2026).
   Same fix as .explore-grid. */
.cat-grid{display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:22px; align-items:start; padding:14px 0 56px}
@media(max-width:960px){.cat-grid{grid-template-columns:minmax(0,1fr)}}
/* Long category lists: rows past ROW_CAP carry .over and stay hidden until "Show all".
   The cap is released by app.js whenever a filter is active, otherwise a filtered row that
   matched would stay hidden by this rule and the filter would look broken. */
#biz-list.capped .rl.over{display:none}
#biz-list:not(.capped) .showall{display:none}
.showall{
  display:block; width:100%; margin:16px 0 4px; padding:14px 16px;
  border:1px solid var(--line); background:var(--card); border-radius:var(--r-panel);
  font-family:inherit; font-size:var(--fs-md); font-weight:700; color:var(--green); cursor:pointer;
}
.showall:hover{background:var(--mint); color:var(--on-mint); border-color:var(--mint)}

.rl{
  display:flex; gap:18px; background:var(--card); border:1px solid var(--line);
  border-radius:var(--r); padding:16px; margin-bottom:14px; transition:var(--tr-card); position:relative;
}
.rl:hover{box-shadow:var(--shadow); border-color:var(--mint-2)}
.rl .ph{position:relative; width:190px; flex:none; border-radius:var(--r-ctl); overflow:hidden; align-self:stretch; min-height:140px; background:var(--mint)}
.rl .ph img{width:100%; height:100%; object-fit:cover; position:absolute; inset:0}
.rl .ph .ph-ini{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:var(--fs-5xl); font-weight:800; color:var(--green); opacity:.55;
}
.rl .bd{flex:1; min-width:0; display:flex; flex-direction:column; gap:8px}
.rl .bd .nm{display:flex; align-items:center; gap:8px; font-size:var(--fs-xl); color:var(--ink); font-weight:750; flex-wrap:wrap}
/* Rank number, moved off the photo and onto the name - "1. Trust Law Chambers", matching the
   reference. Same weight/colour as the name so it reads as one title, not a separate badge. */
.rl .bd .nm .rk{font-weight:800; color:var(--ink)}
.rl .bd .nm a:hover{color:var(--green)}
.rl .bd .where{display:flex; align-items:center; gap:6px; font-size:var(--fs-sm); color:var(--faint)}
.rl .bd .where svg{width:14px; height:14px; flex:none; color:var(--faint)}
.rl .bd .where em{font-style:normal; color:var(--faint); font-weight:700}
.rl .bd .where em.closed-pill{color:var(--danger)}
.rl .bd p{font-size:var(--fs-base); line-height:var(--lh-body)}
/* Restaurant keyword checklist: cuisine + services, each with a flag-yellow tick. Replaces the
   plain description on restaurant cards only (see keywordTags() in gen.js). */
.rl .bd .kw-list{display:flex; flex-wrap:wrap; gap:6px 16px; margin:0}
.rl .bd .kw-list li{display:flex; align-items:center; gap:7px; font-size:var(--fs-base); color:var(--ink); font-weight:600}
.rl .bd .kw-list svg{width:16px; height:16px; flex:none; color:var(--amber)}
.rl .foot{max-width:420px}
@media(max-width:640px){
  .rl{flex-direction:column; gap:12px}
  .rl .ph{width:100%; height:160px; align-self:auto}
  .rl .foot{max-width:none}
}
.side .panel + .panel{margin-top:16px}
.panel{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:22px}
.panel h2,.panel h3{font-size:var(--fs-lg); margin-bottom:14px; display:flex; align-items:center; justify-content:space-between}
.panel h2 span,.panel h3 span{font-size:var(--fs-sm); color:var(--faint); font-weight:600}
.panel p{font-size:var(--fs-base)}
.panel p + p{margin-top:10px}
.rel a{display:flex; align-items:center; justify-content:space-between; font-size:var(--fs-base); font-weight:600; color:var(--body); padding:8px 0; border-bottom:1px dashed var(--line)}
.rel a:last-child{border-bottom:0}
.rel a:hover{color:var(--green)}
.rel a svg{color:var(--faint)}
.seo-copy{border-top:1px solid var(--line); padding:30px 0 54px}
.seo-copy h2{font-size:var(--fs-xl); margin-bottom:10px}
.seo-copy p{font-size:var(--fs-base); max-width:760px}
.seo-copy p + p{margin-top:10px}

/* business profile */
.prof-head{display:flex; align-items:flex-start; gap:20px; padding:22px 0 0; flex-wrap:wrap}
.avatar{
  width:46px; height:46px; border-radius:var(--r-panel); flex:none;
  display:flex; align-items:center; justify-content:center;
  font-weight:800; font-size:var(--fs-xl); color:#fff; letter-spacing:-.02em; background:var(--green);
}
.prof-head .avatar{width:76px; height:76px; border-radius:var(--r-lg); font-size:var(--fs-4xl)}
.prof-head .mid{flex:1; min-width:240px}
.prof-head h1{font-size:var(--fs-display); display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.badge{
  display:inline-flex; align-items:center; gap:6px; font-size:var(--fs-xs); font-weight:700;
  letter-spacing:.05em; text-transform:uppercase; color:var(--rw-green);
  background:var(--rw-green-soft); padding:4px 12px; border-radius:var(--r-pill); transform:translateY(2px);
}
.prof-head .sub{margin-top:8px; display:flex; align-items:center; gap:14px; flex-wrap:wrap; font-size:var(--fs-base); color:var(--faint)}
.prof-head .chips{margin-top:12px; display:flex; gap:8px; flex-wrap:wrap}
.prof-head .chips a{font-size:var(--fs-sm); font-weight:650; background:var(--mint); color:var(--on-mint); padding:6px 12px; border-radius:var(--r-pill)}
.prof-head .chips a:hover{background:var(--mint-2)}
.gallery{display:grid; grid-template-columns:2fr 1fr 1fr; grid-template-rows:130px 130px; gap:10px; padding-bottom:8px}
.gallery a{border-radius:var(--r-panel); overflow:hidden; position:relative; display:block; background:var(--mint)}
.gallery a:first-child{grid-row:1/3}
.gallery img{width:100%; height:100%; object-fit:cover; position:absolute; inset:0; transition:transform .35s}
@media(max-width:640px){.gallery{grid-template-columns:1fr 1fr; grid-template-rows:120px 120px}.gallery a:first-child{grid-row:auto; grid-column:1/3}}
.prof-grid{display:grid; grid-template-columns:1fr 360px; gap:22px; align-items:start; padding:16px 0 64px}
@media(max-width:960px){.prof-grid{grid-template-columns:1fr}}
.prof-grid .panel + .panel{margin-top:18px}
.svc{display:flex; flex-wrap:wrap; gap:10px 20px}
.svc div{display:flex; align-items:center; gap:7px; font-size:var(--fs-base); font-weight:600; color:var(--ink)}
.svc svg{color:var(--amber); flex:none}
.rev{border-top:1px solid var(--line); padding-top:16px; margin-top:16px}
.rev:first-of-type{border-top:0; padding-top:0; margin-top:0}
.rev .rh{display:flex; align-items:center; gap:10px; margin-bottom:6px}
.rev .rh .avatar{width:34px; height:34px; border-radius:50%; font-size:var(--fs-base)}
.rev .rh b{font-size:var(--fs-base); color:var(--ink)}
.rev .rh span{font-size:var(--fs-sm); color:var(--faint)}
/* A review's own score: the same blue tiles as listing ratings, not the gold star characters it
   used to print (2.14:1 on white, and read out glyph by glyph). The filled tiles carry the score at
   4.9:1; the role="img" label gives screen readers "4 / 5". */
.rev .rv-stars{margin-top:4px; gap:10px}
/* the rule above also caught the initial inside .avatar: grey on blue, 1.1:1 */
.rev .rh .avatar{color:#fff}
.rev p{font-size:var(--fs-base)}
.side .row{display:flex; gap:12px; padding:12px 0; border-bottom:1px solid var(--line); font-size:var(--fs-base); align-items:flex-start}
.side .row:last-child{border-bottom:0}
.side .row svg{color:var(--green); margin-top:2px}
.side .row b{color:var(--ink); font-weight:650}
.side .row a:hover{color:var(--green)}
.hours{width:100%; font-size:var(--fs-sm); border-collapse:collapse}
.hours td{padding:6px 0; border-bottom:1px dashed var(--line)}
.hours tr:last-child td{border-bottom:0}
.hours td:last-child{text-align:right; color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums}
.hours .today td{color:var(--green); font-weight:700}
.open-pill{color:var(--faint); font-weight:700}
.open-pill b{color:var(--green)}
.closed-pill{color:var(--danger); font-weight:700}

/* map placeholder */
.map{
  height:150px; border-radius:var(--r-ctl); background:
    linear-gradient(rgba(0,119,179,.06),rgba(0,119,179,.06)),
    repeating-linear-gradient(0deg,transparent 0 28px,var(--line) 28px 29px),
    repeating-linear-gradient(90deg,transparent 0 28px,var(--line) 28px 29px),
    var(--paper);
  position:relative; margin-bottom:10px; border:1px solid var(--line); display:block;
}
.map .pin{position:absolute; color:var(--green)}
.map span{position:absolute; left:0; right:0; bottom:8px; text-align:center; font-size:var(--fs-xs); color:var(--faint)}

/* forms */
.form label{display:block; font-size:var(--fs-sm); font-weight:700; color:var(--ink); margin:12px 0 6px}
.form label .req{color:var(--danger); margin-left:3px}
.form input,.form textarea,.form select{
  width:100%; font:inherit; font-size:var(--fs-base); padding:10px 12px; color:var(--ink);
  border:1.5px solid var(--line); border-radius:var(--r-ctl); background:var(--paper); outline:none;
}
.form input:focus,.form textarea:focus,.form select:focus{border-color:var(--green)}
.form .btn{width:100%; margin-top:14px}
.note{font-size:var(--fs-xs); color:var(--faint); margin-top:10px; text-align:center}
.form-page{max-width:640px; margin:0 auto; padding:34px 20px 70px}

/* Help and contact (/contact/, 28 Sep 2026): direct channels, a topic list per audience, the
   support form. Built from existing parts: .chip-btn actions, .panel, .acct-menu rows, .form. */
.hc{max-width:960px; margin:0 auto; padding:34px 20px 70px}
.hc-head{max-width:640px; margin-bottom:var(--sp-6)}
.hc-head h1{font-size:var(--fs-display); margin-bottom:10px}
.hc-head .lead{font-size:var(--fs-md); margin-bottom:var(--sp-4)}
.hc-direct{display:flex; flex-wrap:wrap; gap:var(--sp-2); max-width:480px}
.hc-direct .chip-btn{flex:1 1 96px; min-height:44px}
/* below 360px three labelled buttons cannot share a row; stack them rather than leave Email alone */
@media(max-width:359px){.hc-direct{flex-direction:column} .hc-direct .chip-btn{flex:none}}
.hc-grid{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-4); margin-bottom:var(--sp-4)}
@media(max-width:760px){.hc-grid{grid-template-columns:minmax(0,1fr)}}
.hc-grid .panel > p{font-size:var(--fs-base); color:var(--faint); margin:-6px 0 var(--sp-1)}
.hc .am-row > span{white-space:normal}   /* topic labels wrap instead of truncating on phones */
#msg{scroll-margin-top:84px}
@media(max-width:760px){#msg{scroll-margin-top:130px}}
.hc-report{display:inline-block; margin-top:var(--sp-3); font-size:var(--fs-sm); color:var(--faint); text-decoration:underline; text-underline-offset:3px}
.hc-report:hover{color:var(--green)}
.form-page h1{font-size:var(--fs-display); margin-bottom:10px}
.form-page .lead{font-size:var(--fs-md); margin-bottom:22px}
.form-ok{background:var(--mint); border:1px solid var(--mint-2); color:var(--on-mint); border-radius:var(--r-panel); padding:16px 18px; font-weight:600; margin-bottom:20px; display:none}

/* account page */
.acct{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:10px}
@media(max-width:760px){.acct{grid-template-columns:1fr}}
.acct .panel h2{margin-bottom:8px}
.acct .panel p{margin-bottom:14px}
@media(max-width:640px){.hdr .signin{display:none}}

/* sticky mobile action bar */
.actbar{display:none}
@media(max-width:760px){
  .actbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:50;
    background:var(--card); border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom, 0px);
    box-shadow:0 -2px 14px rgba(10,46,68,.07);
  }
  /* detail screens: the contextual action bar IS the bottom bar - the global
     tab bar steps aside so the two never stack (the crowded look) */
  body.has-actbar .tabbar{display:none}
  body.has-actbar .prof-grid{padding-bottom:110px}
}
.actbar a{
  flex:1; min-width:0; min-height:56px;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  padding:8px 2px 6px; color:var(--ink); font-size:var(--fs-xs); font-weight:650;
  line-height:1; white-space:nowrap;
}
.actbar a svg{flex:none; width:24px; height:24px}
.actbar a span{max-width:100%; overflow:hidden; text-overflow:ellipsis}
/* Review: the centre action, a step bigger and in the brand blue */
.actbar .ab-mid{color:var(--green); font-weight:750}
.actbar .ab-mid svg{width:30px; height:30px}
.actbar a:active{transform:scale(0.94)}

/* back to top */
#btt{
  position:fixed; right:16px; bottom:86px; z-index:45; width:42px; height:42px;
  border-radius:50%; background:var(--green-ink); color:#fff; display:none;
  align-items:center; justify-content:center; box-shadow:var(--shadow);
}
#btt.show{display:flex}
@media(min-width:761px){#btt{bottom:24px}}

/* pricing */
.plans{display:grid; grid-template-columns:repeat(3,1fr); gap:18px; padding:10px 0 30px}
@media(max-width:960px){.plans{grid-template-columns:1fr; max-width:460px; margin:0 auto}}
.plan{background:var(--card); border:1.5px solid var(--line); border-radius:var(--r-lg); padding:26px; display:flex; flex-direction:column; gap:6px}
.plan.hot{border-color:var(--green); box-shadow:var(--shadow)}
.plan h2{font-size:var(--fs-xl)}
.plan .price{font-size:var(--fs-4xl); font-weight:800; color:var(--ink); letter-spacing:-.02em}
.plan .price small{font-size:var(--fs-sm); color:var(--faint); font-weight:600}
.plan ul{list-style:none; margin:12px 0 18px; display:flex; flex-direction:column; gap:8px}
.plan li{display:flex; gap:10px; font-size:var(--fs-base); align-items:flex-start}
.plan li svg{color:var(--rw-green); margin-top:4px}
.plan .btn{margin-top:auto}


/* ============================================================
   YELP-STYLE HEADER: search bar in the header + category bar
   ============================================================ */
.hdr .wrap{gap:16px}
.logo{flex:none}

/* header search */
.hs{
  flex:1; max-width:600px; min-width:250px; height:42px;
  display:flex; align-items:center; position:relative;
  background:var(--card); border:1.5px solid var(--line); border-radius:var(--r-ctl);
  box-shadow:0 1px 3px rgba(10,46,68,.06);
}
.hs:focus-within{border-color:var(--green); box-shadow:0 2px 10px rgba(0,119,179,.12)}
.hs input{
  flex:1; min-width:70px; border:0; outline:0; font:inherit; font-size:var(--fs-base); font-weight:600;
  color:var(--ink); padding:0 14px; background:transparent;
}
.hs input::placeholder{color:var(--faint); font-weight:500}
.hs-div{width:1px; align-self:stretch; margin:8px 0; background:var(--line); flex:none}
.hs select{
  flex:none; width:126px; border:0; outline:0; font:inherit; font-size:var(--fs-sm); font-weight:700;
  color:var(--ink); cursor:pointer; appearance:none; -webkit-appearance:none;
  padding:0 26px 0 12px;
  background:transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666B6E' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 9px center/12px;
}
.hs-go{
  flex:none; align-self:stretch; width:46px; margin:-1.6px -1.6px -1.6px 0;
  border-radius:0 var(--r-ctl) var(--r-ctl) 0; background:var(--green); color:#fff;
  display:flex; align-items:center; justify-content:center; transition:background .15s;
}
.hs-go:hover{background:var(--green-deep)}
.hs .sugg{top:calc(100% + 6px); border:1px solid var(--line); box-shadow:var(--shadow-float)}

/* header "For business" dropdown (Yelp for Business style) */
.nav-dd{position:relative; padding:22px 0; margin:-22px 0}
.nav-dd-btn{
  display:flex; align-items:center; gap:6px; padding:0; background:none; border:0;
  font:inherit; font-size:var(--fs-base); font-weight:600; color:var(--body); cursor:pointer;
}
.nav-dd-btn svg{color:var(--faint); transition:transform .18s}
.nav-dd:hover .nav-dd-btn,.nav-dd.open .nav-dd-btn{color:var(--green)}
.nav-dd:hover .nav-dd-btn svg,.nav-dd.open .nav-dd-btn svg{transform:rotate(180deg); color:var(--green)}
.nav-dd-menu{
  position:absolute; top:100%; left:-14px; min-width:320px; z-index:60;
  background:var(--card); border:1px solid var(--line); border-radius:var(--r-panel);
  box-shadow:var(--shadow-float); padding:8px; display:none;
}
.nav-dd:hover .nav-dd-menu,.nav-dd.open .nav-dd-menu{display:block}
.nav-dd-menu a{
  display:flex; align-items:center; gap:12px; padding:12px 12px; border-radius:var(--r-row);
  font-size:var(--fs-base); font-weight:600; color:var(--body); white-space:nowrap;
}
.nav-dd-menu a svg{color:var(--ink); flex:none}
.nav-dd-menu a:hover{background:var(--mint); color:var(--on-mint)}
.nav-dd-menu a:hover svg{color:var(--on-mint)}
.nav-dd-menu hr{border:0; border-top:1px solid var(--line); margin:6px 4px}

/* category bar */
.catbar{background:var(--card); border-top:1px solid var(--line); border-bottom:1px solid var(--line)}
.catbar .wrap{display:flex; align-items:center; gap:2px; height:47px}
.cb{position:relative; height:100%; display:flex; align-items:center}
.cb > a{
  display:flex; align-items:center; gap:8px; padding:8px 14px; border-radius:var(--r-ctl);
  font-size:var(--fs-base); font-weight:650; color:var(--ink); white-space:nowrap;
}
.cb > a svg{color:var(--faint); transition:transform .18s}
.cb:hover > a,.cb.open > a{background:var(--mint); color:var(--on-mint)}
.cb:hover > a svg,.cb.open > a svg{transform:rotate(180deg); color:var(--on-mint)}
.cb-menu{
  position:absolute; top:calc(100% - 4px); left:0; min-width:232px; z-index:60;
  background:var(--card); border:1px solid var(--line); border-radius:var(--r-panel);
  box-shadow:var(--shadow-float); padding:8px; display:none;
}
/* Hover, or .open from app.js (ArrowDown on the focused link). NOT :focus-within - that opened
   every panel as keyboard users tabbed along the bar and dragged them through ~100 panel links. */
.cb:hover .cb-menu,.cb.open .cb-menu{display:block}
/* items near the right edge anchor their panel to the right so it never overflows */
.cb:nth-last-child(-n+3) .cb-menu{left:auto; right:0}
.cb-menu a{display:block; padding:10px 12px; border-radius:var(--r-row); font-size:var(--fs-base); font-weight:600; color:var(--body); white-space:nowrap}
.cb-menu a:hover{background:var(--mint); color:var(--on-mint)}
/* Yelp-style mega panel */
/* width follows the longest label set so no column is ever clipped,
   capped so the panel can never run past the viewport edge */
.cb-mega{min-width:0; width:max-content; max-width:min(1000px,calc(100vw - 28px)); padding:14px 14px 8px}
.cb-mega-grid{display:grid; grid-template-columns:repeat(3,minmax(0,max-content)); gap:2px 18px}
.cb-mega-grid a{
  display:flex; align-items:center; gap:12px; padding:10px 10px; border-radius:var(--r-ctl);
  font-size:var(--fs-base); font-weight:600; color:var(--body);
}
.cb-mega-grid a svg{color:var(--ink); flex:none}
.cb-mega-grid a:hover{background:var(--mint); color:var(--on-mint)}
.cb-mega-grid a:hover svg{color:var(--on-mint)}
/* last cell of the More grid: same tile shape, brand colour so it reads as the way out */
.cb-mega-grid a.cb-mega-all{color:var(--green); font-weight:700}
.cb-mega-grid a.cb-mega-all svg{color:currentColor}
.cb-mega-foot{border-top:1px solid var(--line); margin-top:10px; padding:6px 2px 2px}
.cb-mega-foot a{display:inline-flex; padding:8px 10px; border-radius:var(--r-row); font-size:var(--fs-base); font-weight:700; color:var(--green)}
.cb-mega-foot a:hover{background:var(--mint); color:var(--on-mint)}
.cb-loc{
  margin-left:auto; display:flex; align-items:center; gap:8px; padding:8px 12px;
  border-radius:var(--r-ctl); font-size:var(--fs-base); font-weight:650; color:var(--ink); white-space:nowrap;
}
.cb-loc svg{color:var(--green)}
.cb-loc:hover{background:var(--mint); color:var(--on-mint)}

/* anchor targets clear the sticky header */
[id]{scroll-margin-top:80px}
/* the phone header (logo row + search) is ~118px tall and sticky - anchors must clear it
   or the jumped-to section hides behind it (the Add-review -> Add-photos confusion) */
@media(max-width:760px){ [id]{scroll-margin-top:132px} }

/* ---- needs pages (/<city>/plan/<need>/) : cross-category "plan a thing" ----
   Role sections reuse the .rl card, so only the section chrome is new here. */
.nd-sec{margin:34px 0 8px}
.nd-sec h2{
  display:flex; align-items:center; gap:10px;
  font-size:var(--fs-subhead); letter-spacing:-.02em; margin:0 0 14px;
}
.nd-sec h2 svg{color:var(--green); flex:none}
.nd-n{
  font-size:var(--fs-sm); font-weight:700; color:var(--body); background:var(--mint);
  border-radius:var(--r-pill); padding:4px 10px; margin-left:2px;
}
.rel-all{
  display:inline-flex; align-items:center; gap:6px; font-size:var(--fs-base); font-weight:700;
  color:var(--green); padding:6px 0 2px;
}
.rel-all:hover{text-decoration:underline}
.rel-all svg{color:currentColor}

/* responsive header */
@media(max-width:1380px){
  /* the nav now carries the For business dropdown, so the search bar gets
     its own row earlier - otherwise the French header overflows */
  .hdr .wrap{flex-wrap:wrap; height:auto; padding-top:10px; padding-bottom:12px; row-gap:10px}
  .hs{order:10; flex-basis:100%; max-width:none}
}
@media(max-width:1120px){
  /* narrow desktops: two columns keep the panel inside the window */
  .cb-mega-grid{grid-template-columns:repeat(2,minmax(0,max-content))}
}
/* Bar width MEASURED at V=52 (Hotels moved into More/Travel): 1034px in EN, 1012px in FR.
   Below that it must scroll INSIDE itself or the whole page scrolls sideways. overflow-x:auto
   also clips the absolutely-positioned panels, so hover panels switch off at the same
   breakpoint - they cannot open usefully in a scrolling strip, and hover is the wrong
   interaction on the touch devices in that range anyway. 1080 leaves ~46px of headroom over
   the EN measurement. If a bar item is ever added, RE-MEASURE both languages and raise this. */
@media(max-width:1080px){
  .catbar .wrap{overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none}
  .catbar .wrap::-webkit-scrollbar{display:none}
  .cb-menu{display:none !important}
  .cb > a svg{display:none}
  .cb-loc{margin-left:0}
}
@media(max-width:640px){
  /* The lang pill rides row 1 with the logo and Get-listed button; the search bar takes a FULL
     row of its own. It must keep flex-basis:100% here: with flex-basis:0 the .hs box collapsed
     to 13px on a 375px phone while its children (input 56 + select 104 + go 42 = 203px of
     hard minimums) burst out of it, pushing the whole document to 546px and scrolling the page
     sideways - which the owner's rules forbid. Measured 27 Jul 2026. */
  .lang{order:9}
  .hs{order:10; flex:1 1 100%; min-width:0; max-width:none}
  .hs select{width:104px; font-size:var(--fs-sm); padding-left:10px}
  .hs input{min-width:56px; padding:0 10px}
  .hs-go{width:42px}
}

/* Hover motion is desktop-only. A touch tap fires a synthetic :hover that sticks after the
   finger lifts, so on the ~79% Android audience an ungated hover lift stayed stuck on the card
   until the next tap. (hover:hover) and (pointer:fine) together exclude touch and stylus. */
@media (hover: hover) and (pointer: fine){
  .cat:hover{border-color:var(--mint-2); box-shadow:var(--shadow); transform:translateY(-2px)}
  .pcard:hover{box-shadow:var(--shadow); transform:translateY(-2px); border-color:var(--mint-2)}
  .pcard:hover .ph img{transform:scale(1.04)}
  .bt-mini:hover img{transform:scale(1.045)}
  .idea:hover{box-shadow:var(--shadow); transform:translateY(-2px)}
  .idea:hover .ph img{transform:scale(1.04)}
  .pop-card:hover{box-shadow:var(--shadow); transform:translateY(-2px)}
  .qtile:hover .ph img{transform:scale(1.05)}
  .gallery a:hover img{transform:scale(1.04)}
}

/* Press feedback. Touch users never get a legitimate :hover (see the hover block above), so the
   press is the only designed response to their own input. Declared AFTER the hover rules on
   purpose: both set `transform`, and the press must win while the finger is down.
   Small controls take the standard 0.97; large cards take 0.985 because the same ratio on a
   full-width row moves its edges far enough to read as the page shifting. */
.btn, .chip-btn, .subnav a, .filters button{
  transition:background .2s, transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.btn:active, .chip-btn:active, .subnav a:active, .filters button:active{
  transform:scale(0.97);
}
.rl:active, .cat:active, .pcard:active,
.idea:active, .pop-card:active, .exp-card:active, .qtile:active{
  transform:scale(0.985);
}

/* The default tap highlight is a hard-edged grey rectangle that ignores border-radius, so it
   looks wrong on these rounded cards. Suppressed only now that a deliberate press state exists -
   removing it without replacing it would leave taps with no feedback at all. */
.btn, .chip-btn, .subnav a, .filters button,
.rl, .cat, .pcard, .idea, .pop-card, .exp-card, .qtile{
  -webkit-tap-highlight-color:transparent;
}

/* Reduced motion: keep the feedback, drop the movement. A scale is a position change, so it goes;
   a brief opacity dip still confirms the tap landed. */
@media (prefers-reduced-motion:reduce){
  .btn:active, .chip-btn:active, .subnav a:active, .filters button:active,
  .rl:active, .cat:active, .pcard:active,
  .idea:active, .pop-card:active, .exp-card:active, .qtile:active{
    transform:none; opacity:.85;
  }
}

/* ============================================================
   LIST / GRID VIEW TOGGLE (30 Jul 2026)
   The listing rows are full-width by default. Grid view trades the description for density,
   which suits scanning a long category. The choice is remembered in localStorage by app.js.
   ============================================================ */
.viewtog{
  display:inline-flex; margin-left:auto; border:1.5px solid var(--line); border-radius:var(--r-pill);
  overflow:hidden; background:var(--card); flex:none;
}
.viewtog button{
  display:inline-flex; align-items:center; gap:6px; border:0; background:none; cursor:pointer;
  font:inherit; font-size:var(--fs-sm); font-weight:650; color:var(--body);
  padding:8px 14px; border-radius:0;
  transition:background .2s, color .2s, transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.viewtog button svg{width:16px; height:16px; flex:none}
.viewtog button.on{background:var(--green); color:#fff}
.viewtog button:active{transform:scale(0.97)}
/* Icon-only below 520px: the two labels push the district select onto its own line. */
@media(max-width:520px){
  .viewtog button span{display:none}
  .viewtog button{padding:8px 12px}
}

/* Grid view. #biz-list also contains the "show all" button and the quote form as siblings of the
   rows, so both are forced to span every column - otherwise they would sit in a single cell. */
/* --grid-cols is the single source of truth for the column count. app.js reads it to work out how
   many columns the last row is short by. It must NOT infer that from grid-template-columns: an item
   with `grid-column: span 3` creates an implicit third column, so a stale span at mobile width made
   the computed template read "0px 0px 313px" - two collapsed tracks and a broken layout. */
#biz-list.view-grid{
  --grid-cols:3;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px;
}
#biz-list.view-grid > .showall,
#biz-list.view-grid > .panel{grid-column:1 / -1}
#biz-list.view-grid .rl{
  flex-direction:column; gap:12px; margin-bottom:0; padding:12px;
}
#biz-list.view-grid .rl .ph{
  width:100%; height:150px; align-self:auto; min-height:0;
}
#biz-list.view-grid .rl .ph .ph-ini{font-size:var(--fs-4xl)}
#biz-list.view-grid .rl .bd p{display:none}          /* the description is what buys the density */
/* Cards in a row stretch to the tallest (grid default), so the buttons are pushed to the bottom
   to line up across the row instead of floating at ragged heights. .bd is already a flex column
   with flex:1, so margin-top:auto on its last child is all that is needed. */
#biz-list.view-grid .rl .foot{max-width:none; margin-top:auto; padding-top:4px}
/* A trailing card widened by app.js to complete the last row. It reverts to the horizontal
   photo-left layout, because a card stretched across 2-3 columns with a full-width photo on top
   looks stretched, while the horizontal form reads as a normal listing row. */
#biz-list.view-grid .rl.rl-fill{flex-direction:row; gap:18px; padding:16px}
#biz-list.view-grid .rl.rl-fill .ph{width:190px; height:auto; align-self:stretch; min-height:120px; flex:none}
#biz-list.view-grid .rl.rl-fill .ph .ph-ini{font-size:var(--fs-5xl)}
#biz-list.view-grid .rl.rl-fill .bd p{display:block}   /* room for the description again */
#biz-list.view-grid .rl.rl-fill .foot{max-width:420px; margin-top:0}
@media(max-width:960px){
  #biz-list.view-grid{--grid-cols:2; grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:520px){
  /* Too narrow for photo-left; keep the filler card stacked like the others. */
  #biz-list.view-grid .rl.rl-fill{flex-direction:column; padding:12px}
  #biz-list.view-grid .rl.rl-fill .ph{width:100%; height:112px; min-height:0}
  #biz-list.view-grid .rl.rl-fill .foot{flex-direction:column; margin-top:auto}
}
@media(max-width:760px){
  #biz-list.view-grid{gap:12px}
  #biz-list.view-grid .rl .ph{height:112px}
  /* Call and WhatsApp side by side would each be ~70px wide in a 2-column phone grid. */
  #biz-list.view-grid .rl .foot{flex-direction:column; gap:8px}
  #biz-list.view-grid .rl .foot > *{width:100%}
}

/* ============================================================
   TOUCH TARGETS (30 Jul 2026)
   Every primary control measured 36-41px tall - under the 44x44 minimum, on an audience that is
   ~79% Android touch. Raised with min-height so labels can still wrap; padding is untouched so
   nothing reflows horizontally.
   ============================================================ */
.subnav a, .chip-btn, .filters button, .filters-sel, .viewtog button,
.btn, .hs-go, .showall, .cb-loc{
  min-height:44px;
}
.subnav a, .chip-btn, .filters button, .viewtog button{
  align-items:center;
}

/* ============================================================
   PHONE TAB BAR (30 Jul 2026)
   The iOS-app pattern: persistent bottom tabs, five destinations, labels always visible.
   Phone only - hidden from 761px up, where the header nav and mega-menu already do this job.
   Safe areas: the bar pads itself by env(safe-area-inset-bottom) so it clears the iPhone home
   indicator, and <body> gains matching bottom padding so list content is never trapped under it.
   Icons are the site's own SVG set (never emoji) at a single 24px size.
   ============================================================ */
.tabbar{display:none}
@media(max-width:760px){
  .tabbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:60;
    background:var(--card); border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom, 0px);
    box-shadow:0 -2px 14px rgba(10,46,68,.07);
  }
  .tabbar a{
    flex:1; min-width:0; min-height:52px;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
    padding:8px 2px 6px; color:var(--faint); text-decoration:none;
    font-size:var(--fs-xs); font-weight:650; line-height:1;
    transition:color .2s, transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
    -webkit-tap-highlight-color:transparent;
  }
  .tabbar a svg{width:24px; height:24px; flex:none}
  .tabbar a span{
    max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .tabbar a[aria-current="page"]{color:var(--green)}
  /* Press feedback only on the icon+label, so the bar itself never changes bounds (no jitter). */
  .tabbar a:active{transform:scale(0.94)}

  /* Content must clear the fixed bar: tab height + safe area. */
  body{padding-bottom:calc(64px + env(safe-area-inset-bottom, 0px))}
  /* Back-to-top was pinned 86px up; lift it clear of the tab bar instead of overlapping it. */
  #btt{bottom:calc(76px + env(safe-area-inset-bottom, 0px))}
}
@media(max-width:760px) and (prefers-reduced-motion:reduce){
  .tabbar a:active{transform:none; opacity:.7}
}

/* ============================================================
   PHONE FEED (30 Jul 2026) - the Yelp-app card placement
   One business per row, full width, photo area on TOP rather than beside the text. Cards lose
   their border and radius and are separated by a divider, which is how the app presents a feed.
   Applies to the default list view only; the 2-column Grid view is left alone as the compact
   alternative the user can switch to.
   ============================================================ */
@media(max-width:760px){
  #biz-list:not(.view-grid) .rl{
    flex-direction:column; gap:10px;
    border:0; border-radius:0; box-shadow:none;
    border-bottom:1px solid var(--line);
    margin-bottom:0; padding:14px 16px 16px;
  }
  #biz-list:not(.view-grid) .rl:hover{box-shadow:none; border-color:var(--line)}
  /* Photo area: full width of the card, 4:3-ish band. Rounded like the app, not edge-to-edge. */
  #biz-list:not(.view-grid) .rl .ph{
    width:100%; height:200px; align-self:auto; min-height:0; border-radius:var(--r-ctl);
  }
  #biz-list:not(.view-grid) .rl .ph .ph-ini{font-size:var(--fs-5xl)}
  /* A listing with no photo shows a compact square category tile (the :has rule outranks the
     plain .ph rule on specificity, so the square must be set here too). Sized deliberately larger
     than a small icon chip (160px, up from an earlier 112px that read as too small) while staying
     well short of the 200px real-photo band, so a placeholder still reads as smaller than a photo. */
  #biz-list:not(.view-grid) .rl .ph:not(:has(img)){width:160px; height:160px}
  #biz-list:not(.view-grid) .rl .bd{gap:6px}
  #biz-list:not(.view-grid) .rl .foot{max-width:none; margin-top:2px}

  /* Horizontal photo strip, for listings that actually have more than one photo. Scrolls with
     momentum and snaps, like the app's carousel. Guarded by the markup: the strip element is only
     emitted when img.length > 1, so the 6,210 photo-less listings never render an empty carousel. */
  #biz-list:not(.view-grid) .rl .phstrip{
    display:flex; gap:6px; overflow-x:auto; scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch; scrollbar-width:none;
  }
  #biz-list:not(.view-grid) .rl .phstrip::-webkit-scrollbar{display:none}
  #biz-list:not(.view-grid) .rl .phstrip .ph{
    flex:0 0 72%; scroll-snap-align:start; height:200px;
  }
}

/* ============================================================
   CARD ACTION ROW (30 Jul 2026)
   Per the reference: an outlined category pill on the left, text-only action pills on the right.
   One shape (full pill), one size, no icons. 44px min height is kept from the touch-target pass.
   ============================================================ */
/* Two actions only: Call sits on the left edge, WhatsApp on the right (space-between).
   A card with a single action (claim, or phone-only) keeps it on the left. */
.foot{display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap}
/* Action pills: same shape and size as each other, text only. */
.foot .chip-btn{
  flex:0 0 auto; min-height:44px; padding:8px 22px;
  border-radius:var(--r-pill); font-size:var(--fs-sm); font-weight:700;
  justify-content:center;
}
/* WhatsApp action: Rwandan flag green, white text. #20603D on white is 8.4:1; white text on
   #20603D is 8.4:1 - both comfortably past the 4.5 floor. */
.chip-btn--wa{background:var(--rw-green); color:#fff}
.chip-btn--wa:hover{background:var(--on-rw-green)}
@media(max-width:400px){
  .foot .chip-btn{padding:8px 18px}
}

/* ============================================================
   SQUARE THUMBNAILS + CATEGORY-ICON PLACEHOLDERS (30 Jul 2026)
   Photo tiles are square everywhere, and a listing with no photo shows its CATEGORY icon on the
   tinted tile instead of the first letter of its name, so the thumbnail says what the business
   does. Deliberately not stock photos of other premises - a photo of someone else's restaurant
   on a listing reads as a photo OF that restaurant.
   ============================================================ */
.ph-cat svg{width:24%; height:24%; max-width:44px; max-height:44px; color:var(--green); opacity:.5}

/* Desktop list rows: the 190px photo becomes a 190px square. */
.rl .ph{aspect-ratio:1/1; align-self:flex-start; min-height:0}

/* With real photos, the strip tiles are squares like the app's carousel. (The placeholder-only
   square sizing lives in the PHONE FEED block above, on the more specific :not(:has(img))
   selector - a duplicate unscoped rule used to live here and silently forced EVERY phone-feed
   photo, including a single real photo, down to a small square. No listing has exactly one photo
   today so it went unnoticed, but it was a real specificity bug.) */
@media(max-width:760px){
  /* one full tile + half the next visible, so the strip invites a sideways scroll */
  #biz-list:not(.view-grid) .rl .phstrip .ph{
    flex:0 0 64%; width:auto; height:auto; aspect-ratio:1/1;
  }
}
/* Grid view keeps its own sizing but goes square too. */
#biz-list.view-grid .rl .ph{width:100%; height:auto; aspect-ratio:1/1}

/* ============================================================
   RED "UNCLAIMED" LABEL + 3-TILE PLACEHOLDER STRIP (30 Jul 2026)
   Every unclaimed business is flagged in red right after its name, and photo-less
   listings show a strip of three tinted cuisine/category tiles instead of one big
   square - the Yelp-style card look. Real photos replace the tiles automatically
   once a listing has img entries (bizPhotoArea emits them first).
   ============================================================ */
.uncl{color:var(--danger); font-weight:700; font-size:var(--fs-xs); letter-spacing:.04em; text-transform:uppercase}
.rl .phstrip{display:flex; gap:6px; overflow-x:auto; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch; scrollbar-width:none}
.rl .phstrip::-webkit-scrollbar{display:none}
/* placeholder tiles take the SAME size as real photo tiles - big squares, scroll sideways */
.rl .phstrip.ph-ph .ph{flex:0 0 190px; aspect-ratio:1/1; align-self:flex-start; min-height:0; scroll-snap-align:start}
.rl .ph.ph-t1{background:var(--amber-soft)}
.rl .ph.ph-t2{background:var(--rw-green-soft)}
.rl .ph.ph-t1 .ph-cat svg{color:var(--star)}
.rl .ph.ph-t2 .ph-cat svg{color:var(--rw-green)}
/* A strip of three is 582px wide. Once the list column is narrower than ~900px (961-1200px
   screens, where the sidebar still shows) the text beside it was crushed to a few pixels and
   names clipped. The text keeps 260px; the strip, already a sideways scroller, gives way. */
@media(min-width:761px){
  #biz-list:not(.view-grid):not(.view-compact) .rl .bd{min-width:260px}
}
@media(max-width:760px){
  #biz-list:not(.view-grid) .rl .phstrip.ph-ph{width:100%}
  #biz-list:not(.view-grid) .rl .phstrip.ph-ph .ph{flex:0 0 64%; width:auto; height:auto; aspect-ratio:1/1}
}

/* ============================================================
   COMPACT CATEGORY-PAGE HEADER ON PHONES (30 Jul 2026)
   The header stacked six full-width rows (crumb, title, 2-line meta, chips, two rows
   of filter pills) before the first business. Tightened: smaller title, one-line meta,
   and the filter pills join the chips pattern - a single sideways-scrolling row.
   Touch height stays 44px; only padding, font and wrapping change.
   ============================================================ */
@media(max-width:760px){
  .cat-head{padding:8px 0 0}
  .cat-head h1{font-size:24px; margin-bottom:2px}
  .cat-head .meta{font-size:var(--fs-sm); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  .subnav{padding-top:8px; padding-bottom:2px}
  .filters{flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; padding:8px 0 4px; align-items:center}
  .filters::-webkit-scrollbar{display:none}
  .filters button, .filters .filters-sel, .filters > *{flex:0 0 auto}
}

/* No hero on the phone homepage (owner's call, 30 Jul 2026, per the Yelp reference):
   mobile opens straight into search + category tiles. Desktop keeps the bento hero. */
@media(max-width:760px){
  .jd-hero{display:none}
}

/* Yelp-style phone homepage (owner's call, 30 Jul 2026): search bar then category tiles,
   nothing between. Hides the stats band, the section heading words, and the catbar nav -
   HOMEPAGE ONLY (scoped via :has(.jd-hero); every other page keeps its catbar). */
@media(max-width:760px){
  body:has(.jd-hero) .catbar{display:none}
  body:has(.jd-hero) .stats{display:none}
  body:has(.jd-hero) #categories .sec-head{display:none}
  body:has(.jd-hero) #categories{padding-top:30px; padding-bottom:30px}
}

/* ============================================================
   YELP-STYLE CATEGORY GRID (30 Jul 2026, owner's reference)
   Two-tone icons: navy outline with the site blue as the accent color on the last
   drawn shape (Yelp does navy + red; ours is navy + blue). On the phone homepage the
   tiles lose their card boxes and become a compact 4-across icon + name grid.
   ============================================================ */
.cat .ic svg:not(.duo) *{stroke:var(--green-ink)}
.cat .ic svg:not(.duo) > :last-child{stroke:var(--green)}
@media(max-width:760px){
  body:has(.jd-hero) .cats{grid-template-columns:repeat(4,1fr); gap:18px 4px}
  body:has(.jd-hero) .cat{background:none; border:none; padding:4px 2px}
  body:has(.jd-hero) .cat .ic{width:36px; height:36px; margin:0 auto 6px; background:none; border-radius:0}
  body:has(.jd-hero) .cat .ic svg{width:30px; height:30px}
  body:has(.jd-hero) .cat b{font-size:var(--fs-xs); font-weight:650}
  body:has(.jd-hero) .cat span{display:none}
}

/* "7 + More" phone homepage grid: tiles past the 7th hide behind the More tile */
.cat-more{display:none; cursor:pointer; font:inherit}
@media(max-width:760px){
  body:has(.jd-hero) .cats:not(.x) .cat-x{display:none}
  body:has(.jd-hero) .cats .cat-more{display:block}
  body:has(.jd-hero) .cats.x .cat-more{display:none}
}

/* Thin dividers between homepage sections (owner's call, 30 Jul 2026) */
.sec + .sec, .sec + .seo, .seo + .sec{border-top:1px solid var(--line)}

/* Guidelines pass (30 Jul 2026): no tap delay on interactive elements, and the EN/FR
   toggle gets a real 44px touch target (visual size unchanged, hit area grown). */
a,button,select,input,label{touch-action:manipulation}
.lang a{padding:13px 14px; margin:-9px -6px; border-radius:var(--r-sm)}

/* ============================================================
   BLUE HEADER ON PHONES (30 Jul 2026, owner's Yelp reference)
   The brand blue flows from the browser chrome (theme-color #0077B3) down through
   the header and ends below the search bar - logo and controls go white-on-blue,
   the white search bar pops against it like Yelp's. Phones only; desktop unchanged.
   ============================================================ */
@media(max-width:760px){
  .hdr{background:var(--green); border-bottom:0}
  .hdr .logo > span:first-child, .hdr .logo .lg2{color:#fff}
  .hdr .logo i{background:var(--amber)}
  .hdr .btn{background:#fff; color:var(--green-deep); border-color:#fff}
  .hdr .lang{border-color:rgba(255,255,255,.5)}
  .hdr .lang a{color:rgba(255,255,255,.8)}
  .hdr .lang a.on{background:#fff; color:var(--green-deep)}
  .hs{border-color:transparent; box-shadow:none}
  /* search bar all white: the magnifier button joins the white bar, icon in dark ink */
  .hs-go{background:#fff; color:var(--green-ink); margin:0; align-self:stretch; height:auto; min-height:0; border-radius:0 var(--r-row) var(--r-row) 0}
  .hs-go:hover{background:#fff}
  /* logo centered in the top row, button left, language toggle right (Yelp layout) */
  .hdr .wrap{flex-wrap:wrap}
  .hdr .btn{order:1; margin-left:0}
  .hdr .logo{order:2; flex:1; justify-content:center}
  .hdr .lang{order:3}
  .hdr .hs{order:4; flex-basis:100%}
}
/* Narrow phones. Row 1 - Get listed, wordmark, EN/FR - needs ~320px in English and ~340px in
   French ("Inscription gratuite") at the sizes above, so the language pill wrapped onto its own
   row and the header grew from 118px to 165px: English below 360px, French below 390px (found
   28 Sep 2026). Tighter gaps and one step down on the wordmark and button text keep one row; no
   copy changes. The EN/FR links keep their -9px/-6px margin trick (44px hit area) and only lose
   horizontal padding; overriding the padding alone collapses the pill. Button and pill never
   shrink - the wordmark cell (flex:1) absorbs the squeeze. */
@media(max-width:359px){
  .hdr .wrap{column-gap:8px}
  .hdr .logo{font-size:var(--fs-xl)}
  .hdr .btn{flex:none; font-size:var(--fs-xs); padding:8px 9px}
  .hdr .lang{flex:none}
  .hdr .lang a{padding:13px 10px}
  /* French at 320: the longer button leaves 3px short even so; one more step on the wordmark
     buys ~6px of slack, so a wider fallback font cannot tip it back onto two rows */
  html[lang="fr"] .hdr .logo{font-size:var(--fs-lg)}
}
@media(min-width:360px) and (max-width:389px){
  html[lang="fr"] .hdr .wrap{column-gap:8px}
  html[lang="fr"] .hdr .logo{font-size:var(--fs-xl)}
  html[lang="fr"] .hdr .btn{flex:none; font-size:var(--fs-xs); padding:8px 9px}
  html[lang="fr"] .hdr .lang{flex:none}
  html[lang="fr"] .hdr .lang a{padding:13px 10px}
}

/* "Add business with this name" row (Yelp-style, 31 Jul 2026): shopfront-with-plus icon,
   name bold with the action label stacked under it, in the site blue */
.sugg a.gl-add .gl-add-ic{flex:none; width:40px; height:40px; border-radius:var(--r-ctl); background:var(--mint); color:var(--green); display:flex; align-items:center; justify-content:center}
.sugg a.gl-add .gl-add-t{display:flex; flex-direction:column; gap:2px; margin-left:0; white-space:normal; min-width:0}
.sugg a.gl-add .gl-add-t b{color:var(--ink); font-size:var(--fs-lg); font-weight:800}
.sugg a.gl-add .gl-add-t span{font-size:var(--fs-sm)}
.sugg a.gl-add .gl-add-t span{margin-left:0; white-space:normal}

/* Step 2 of get-listed (Yelp-style, 31 Jul 2026): email left, skeleton page preview right.
   The skeleton shows the typed business NAME on a wireframe of their future page. */
.gl2-grid{display:grid; grid-template-columns:1fr 1fr; gap:30px; align-items:start}
@media(max-width:760px){.gl2-grid{grid-template-columns:1fr} .gl-skel{display:none}}
.gl-skel-card{border:1px solid var(--line); border-radius:var(--r); padding:24px; background:var(--card); box-shadow:var(--shadow)}
.gl-skel-card b{display:block; font-size:var(--fs-3xl); font-weight:800; color:var(--ink); margin-bottom:10px; overflow-wrap:anywhere}
.sk{height:10px; border-radius:var(--r-sm); background:var(--tile-none); margin:9px 0}
.sk-stars{display:flex; gap:4px; margin:6px 0 4px}
.sk-stars i{width:16px; height:16px; border-radius:var(--r-xs); background:var(--tile-none)}
.sk-row{display:flex; gap:10px; margin-top:18px}
.sk-box{flex:1; aspect-ratio:4/3; border-radius:var(--r-row); background:var(--tile-none)}

/* Step 2 breaks out of the narrow 640px form column on desktop - form left, big page
   skeleton right, using the full screen like the Yelp reference */
@media(min-width:761px){
  #gl-step2{width:min(1060px, calc(100vw - 48px)); margin-left:50%; transform:translateX(-50%); padding:36px 42px}
  #gl-step2 h2{font-size:var(--fs-headline); margin-bottom:10px}
  #gl-step2 .hint{font-size:var(--fs-md)}
  .gl2-grid{grid-template-columns:1fr 1.15fr; gap:56px}
  .gl-skel-card{padding:36px}
  .gl-skel-card b{font-size:var(--fs-4xl)}
  .sk{height:12px; margin:11px 0}
  .sk-stars i{width:20px; height:20px}
}

/* Step 1 of get-listed, Yelp-style (31 Jul 2026): search left, illustrated skyline with a
   live stat card right. Illustration is desktop-only decoration. */
.gl1-grid{display:grid; grid-template-columns:1fr; gap:30px}
.gl-art{position:relative; display:none}
.gl-art svg{width:100%; height:auto; display:block}
.gl-art-card{position:absolute; left:6%; bottom:14%; background:#fff; border-radius:var(--r);
  box-shadow:0 10px 34px rgba(10,46,68,.18); padding:16px 22px; font-size:var(--fs-lg);
  font-weight:700; color:var(--ink); max-width:72%; line-height:1.35}
.gl-art-card b{color:var(--green); font-size:1.25em}
@media(min-width:761px){
  #gl-step1{width:min(1060px, calc(100vw - 48px)); margin-left:50%; transform:translateX(-50%); padding:36px 42px}
  #gl-step1 h2{font-size:var(--fs-headline)}
  #gl-step1 .hint{font-size:var(--fs-md)}
  .gl1-grid{grid-template-columns:1fr 1.1fr; gap:56px; align-items:center}
  .gl-art{display:block}
}

/* On phones, suggestion rows stack name over detail instead of squeezing on one line */
@media(max-width:760px){
  .sugg a{flex-wrap:wrap}
  .sugg a b{width:100%}
  .sugg a span{margin-left:0; white-space:normal}
  .sugg a.gl-add b{width:auto}
}

/* Step 3 phone row: country code + number side by side; number previews on the skeleton */
.gl-phone-row{display:flex; gap:10px}
.gl-phone-row select{flex:0 0 96px; font:inherit; font-size:var(--fs-md); padding:12px 10px;
  border:1.5px solid var(--line); border-radius:var(--r-ctl); background:var(--paper); color:var(--ink)}
.gl-phone-row input{flex:1}
.gl-skel-phone{font-weight:800; color:var(--green); font-size:var(--fs-lg); margin-top:12px}
@media(min-width:761px){
  #gl-step3{width:min(1060px, calc(100vw - 48px)); margin-left:50%; transform:translateX(-50%); padding:36px 42px}
  #gl-step3 h2{font-size:var(--fs-headline)}
  #gl-step3 .hint{font-size:var(--fs-md)}
}

/* "Same as business phone" checkbox row on the get-listed form */
.gl-same{display:flex; align-items:center; gap:9px; font-size:var(--fs-sm); font-weight:600;
  color:var(--body); margin:2px 0 6px; cursor:pointer}
.gl-same input{width:18px; height:18px; accent-color:var(--green)}

/* Opening hours rows on the get-listed form */
.gl-hours{display:flex; flex-direction:column; gap:8px; margin:2px 0 8px}
.gl-hrow{display:flex; align-items:center; gap:6px}
.gl-hday{flex:0 0 72px; font-size:var(--fs-sm); font-weight:650; color:var(--body)}
.gl-hrow input[type=time]{flex:1; min-width:92px; font:inherit; font-size:var(--fs-sm); padding:8px 4px; text-align:center;
  border:1.5px solid var(--line); border-radius:var(--r-row); background:var(--paper); color:var(--ink)}
.gl-hrow input[type=time]:disabled{opacity:.4}
.gl-hdash{color:var(--faint)}
.gl-hclosed{display:flex; align-items:center; gap:6px; font-size:var(--fs-xs); font-weight:600; color:var(--body); cursor:pointer}
.gl-hclosed input{width:16px; height:16px; accent-color:var(--green)}

/* Multi-category chips (Yelp-style, max 3) */
.g2-chips{display:flex; flex-direction:column; gap:6px}
.g2-chips:not(:empty){margin-bottom:10px}
.g2-chip{display:flex; align-items:center; gap:12px; font-size:var(--fs-md)}
.g2-chip b{font-weight:700; color:var(--ink)}
.g2-chip a{color:var(--green); font-weight:700; font-size:var(--fs-sm)}

/* Phone layout for hours rows: day + Closed on the first line, times on the second -
   nothing wraps or pokes out of the panel edge */
@media(max-width:760px){
  .gl-hrow{display:grid; grid-template-columns:1fr 16px 1fr; gap:7px 8px; align-items:center;
           padding-bottom:10px; border-bottom:1px dashed var(--line)}
  .gl-hrow:last-of-type{border-bottom:0}
  .gl-hday{grid-area:1/1/2/2; flex:none}
  .gl-hclosed{grid-area:1/2/2/4; justify-self:end; white-space:nowrap}
  .gl-hrow input[type=time]:nth-of-type(1){grid-area:2/1/3/2}
  .gl-hdash{grid-area:2/2/3/3; text-align:center}
  .gl-hrow input[type=time]:nth-of-type(2){grid-area:2/3/3/4}
}

/* Every tick row: box and words vertically centered on one line */
.gl-same, .gl-hclosed{align-items:center; line-height:1.2}
.gl-same input, .gl-hclosed input{margin:0; flex:none; display:block}

/* The form's generic block-label rule outranks the flex tick rows - restate with
   higher specificity so box and words sit on ONE line, vertically centered */
.form label.gl-same, label.gl-same{display:flex; flex-direction:row; align-items:center; gap:9px; margin:2px 0 6px}
.form label.gl-hclosed, label.gl-hclosed{display:flex; flex-direction:row; align-items:center; gap:6px; margin:0}

/* ============================================================
   FIELD STATES (31 Jul 2026, owner's reference)
   Filling: blue border + soft blue glow. Filled and valid: green + glow + tick.
   Invalid: red + glow. Select chevrons drawn inset, not glued to the edge.
   ============================================================ */
.form select, .gl-phone-row select{
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23566066' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 14px center; padding-right:42px;
}
.form input.f-ok, .form textarea.f-ok, .form select.f-ok, #gl-email.f-ok, #gl-phone.f-ok{
  border-color:var(--ok); box-shadow:0 0 0 4px rgba(31,157,85,.16);
}
.form input.f-ok:not(:focus):not([list]), #gl-email.f-ok:not(:focus), #gl-phone.f-ok:not(:focus){
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%231F9D55' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4.5 12.5 5 5 10-11'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 13px center; padding-right:42px;
}
.form input.f-bad, .form textarea.f-bad, .form select.f-bad, #gl-email.f-bad, #gl-phone.f-bad{
  border-color:var(--danger); box-shadow:0 0 0 4px rgba(192,57,43,.15);
}
.form input.f-bad:not(:focus):not([list]), #gl-email.f-bad:not(:focus), #gl-phone.f-bad:not(:focus){
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23C0392B' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5M12 16.5v.01'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 13px center; padding-right:42px;
}
/* while actively filling, blue always wins */
.form input:focus, .form textarea:focus, .form select:focus, #gl-email:focus, #gl-phone:focus{
  border-color:var(--green); box-shadow:0 0 0 4px rgba(0,119,179,.18); outline:none;
}

/* Duotone category icons: no tinted chip behind them, generous size */
.cat .ic:has(.duo){background:none}
.cat .ic svg.duo{width:30px; height:30px}
@media(max-width:760px){body:has(.jd-hero) .cat .ic svg.duo{width:32px; height:32px}}

/* Site-wide duotone icons: navy outline via the svg's own color, blue accent via --duo.
   On dark or active surfaces both layers flip to white so nothing disappears. */
svg.duo{color:var(--green-ink)}
.subnav a.on .snc svg.duo{color:#fff; --duo:rgba(255,255,255,.85)}
.btn svg.duo, .ftr svg.duo, .cta svg.duo, .chip-btn--wa svg.duo{color:#fff; --duo:rgba(255,255,255,.85)}

/* ============================================================
   COMPACT VIEW (third viewtog option, owner's Yelp reference):
   square photo top-left, name / stars / location beside it, then
   attribute ticks, description and action buttons full width below.
   Appended after the mobile phstrip rules on purpose - equal
   specificity, so source order lets these win in compact mode.
   ============================================================ */
#biz-list.view-compact .rl{display:grid; grid-template-columns:112px minmax(0,1fr); gap:2px 14px; align-items:start}
#biz-list.view-compact .rl .phstrip,
#biz-list.view-compact .rl > .ph{grid-column:1; grid-row:1 / span 3; width:100%; align-self:start}
#biz-list.view-compact .rl .phstrip{display:block; overflow:visible}
#biz-list.view-compact .rl .phstrip .ph{width:100%; aspect-ratio:1/1; min-height:0; display:block; flex:none}
#biz-list.view-compact .rl .phstrip .ph + .ph{display:none}
#biz-list.view-compact .rl > .ph{aspect-ratio:1/1; min-height:0}
#biz-list.view-compact .rl .bd{display:contents}
#biz-list.view-compact .rl .bd > *{grid-column:2; margin:0}
#biz-list.view-compact .rl .bd > .kw-list,
#biz-list.view-compact .rl .bd > p,
#biz-list.view-compact .rl .bd > .foot{grid-column:1 / -1}
#biz-list.view-compact .rl .foot{max-width:none; padding-top:2px}
#biz-list.view-compact .rl .bd > p{display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden}
/* the dash between address and the open/closed pill now lives on the pill itself */
.rl .bd .where em::before{content:"- "; color:var(--faint); font-weight:400}
/* Compact view: address on ONE line - the location text ellipsizes, the
   open/closed pill never gets cut (owner's call). */
#biz-list.view-compact .rl .bd .where{flex-wrap:wrap; min-width:0; row-gap:2px}
#biz-list.view-compact .rl .bd .where .wx{white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; flex:0 1 auto}
#biz-list.view-compact .rl .bd .where em{flex:0 0 100%; white-space:nowrap}
#biz-list.view-compact .rl .bd .where em::before{content:none}
#biz-list.view-compact .rl .bd .nm{display:block}
#biz-list.view-compact .rl .bd .nm > *{vertical-align:middle}
#biz-list.view-compact .rl .bd .nm .rk{margin-right:6px}
#biz-list.view-compact .rl .bd .nm .uncl,#biz-list.view-compact .rl .bd .nm .tag{margin-left:8px}
#biz-list.view-compact .rl .bd .nm{font-size:var(--fs-md)}
#biz-list.view-compact .rl .bd .nm .uncl,#biz-list.view-compact .rl .bd .nm .tag{font-size:10px}
/* Compact view: UNCLAIMED moves out of the name line onto the photo, top-left,
   so names stay on one line (owner's call). White pill so it reads over photos. */
#biz-list.view-compact .rl .bd .nm .uncl{
  position:absolute; top:22px; left:22px; margin:0; z-index:1;
  background:#fff; padding:3px 7px; border-radius:var(--r-sm); font-size:10px;
  box-shadow:0 1px 4px rgba(10,46,68,.18);
}
/* Compact view: the tick-tag row stays on ONE line (owner's call) - smaller text,
   tighter gaps so three tags fit a 375px phone; anything past the edge is clipped. */
#biz-list.view-compact .rl .bd .kw-list{flex-wrap:nowrap; overflow:hidden; gap:10px}
#biz-list.view-compact .rl .bd .kw-list li{flex:none; font-size:var(--fs-sm)}
#biz-list.view-compact .rl .bd .kw-list svg{width:14px; height:14px}
/* Compact view: smaller action pills (owner's call). */
#biz-list.view-compact .rl .foot .chip-btn{min-height:36px; padding:5px 16px; font-size:var(--fs-sm)}
#biz-list.view-compact .rl .bd > .kw-list,
#biz-list.view-compact .rl .bd > p{margin-top:10px}
/* Profile pages without photos: 3 tinted subcategory-icon tiles like the card strips
   (owner's call) - desktop shows all three, phones show one and a half and scroll. */
.phband{display:flex; gap:10px; overflow-x:auto; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch; scrollbar-width:none; padding-bottom:8px}
.phband::-webkit-scrollbar{display:none}
.phband .ph-tile{flex:1 1 0; height:190px; display:flex; align-items:center; justify-content:center; border-radius:var(--r-panel); background:var(--mint); scroll-snap-align:start}
.phband .ph-b1{background:var(--amber-soft)}
.phband .ph-b2{background:var(--rw-green-soft)}
.phband .ph-b1 svg{color:var(--star)}
.phband .ph-b2 svg{color:var(--rw-green)}
@media(max-width:640px){
  .phband .ph-tile{flex:0 0 64%; height:auto; aspect-ratio:1/1}
}
/* Breathing room between the breadcrumb and the photo area on profile pages. */
.gallery, .phband{margin-top:16px}
/* Profile (account) page - Yelp-style Me screen */
.me-head{text-align:center; padding:12px 0 4px}
.me-head .avatar{width:72px; height:72px; border-radius:50%; margin:0 auto 10px; font-size:var(--fs-3xl)}
.me-head h1{font-size:var(--fs-display)}
.me-stats{display:flex; justify-content:center; gap:20px; margin-top:8px; color:var(--faint); font-size:var(--fs-sm); font-weight:600}
.me-stats b{color:var(--ink); margin-right:5px}
.acct-menu{display:flex; flex-direction:column}
.am-row{display:flex; align-items:center; gap:12px; padding:13px 0; border-bottom:1px solid var(--line); font-weight:650; color:var(--ink); font-size:var(--fs-md)}
.am-row:last-child{border-bottom:0; padding-bottom:2px}
.am-row > span{flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.am-row svg{flex:none}
.am-row b{color:var(--faint); font-weight:700}
a.am-row:hover{color:var(--green)}
#viewedlist a{display:flex; align-items:center; justify-content:space-between; gap:12px; padding:9px 0}
#viewedlist a b{min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
#viewedlist a > span{flex:none; color:var(--faint); font-size:var(--fs-sm); max-width:45%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.rec-card{border:1px solid var(--line); border-radius:var(--r-panel); padding:12px 14px; margin-bottom:10px}
.rec-card p{font-size:var(--fs-sm); color:var(--faint); margin:4px 0 10px}
.rec-card > span{display:flex; gap:8px; flex-wrap:wrap}
.rec-card .btn{padding:8px 18px; font-size:var(--fs-sm)}
/* Full-screen in-site map view (category pages) */
.mapov{position:fixed; inset:0; z-index:120; background:var(--paper); display:flex; flex-direction:column}
.mapov[hidden]{display:none}
.mapov-bar{display:flex; align-items:center; gap:12px; padding:12px 16px; border-bottom:1px solid var(--line); background:var(--card)}
.mapov-bar b{font-size:var(--fs-md)}
.mapov-bar span{color:var(--faint); font-size:var(--fs-sm); flex:1}
.mapx{background:var(--amber); border:0; width:38px; height:38px; border-radius:50%; font-size:var(--fs-2xl); font-weight:700; cursor:pointer; flex:none}
#mapdiv{flex:1}
#mapdiv .leaflet-popup-content a{font-weight:700; color:var(--green)}
.mapbtn{display:inline-flex; align-items:center; gap:8px; font:inherit; font-size:var(--fs-sm); font-weight:650; padding:10px 16px; border-radius:var(--r-pill); min-height:44px; border:1.5px solid var(--line); background:var(--card); color:var(--body); cursor:pointer}
.mapbtn svg{width:16px; height:16px}
.mapbtn:hover{background:var(--mint); border-color:var(--mint-2)}
/* Numbered map pins: brand-blue teardrop, number upright inside */
.spin-wrap{background:none; border:none}
.spin{
  width:32px; height:32px; background:var(--green); border:2px solid #fff;
  border-radius:50% 50% 50% 0; transform:rotate(-45deg); transform-origin:center;
  box-shadow:0 2px 6px rgba(10,46,68,.35);
  display:flex; align-items:center; justify-content:center;
}
.spin span{transform:rotate(45deg); color:#fff; font-weight:800; font-size:13px; letter-spacing:-.02em}
/* Preferences card + For-you chips */
.me-prefs-head{display:flex; align-items:flex-start; justify-content:space-between; gap:16px}
.me-prefs-heart{flex:none; margin-top:6px}
.fy-chips{display:flex; flex-wrap:wrap; gap:10px}
.fy-chip{
  display:inline-flex; align-items:center; gap:8px; padding:10px 16px; min-height:44px;
  border-radius:var(--r-pill); border:1.5px solid var(--line); background:var(--card);
  font-weight:650; font-size:var(--fs-sm); color:var(--ink);
}
.fy-chip:hover{background:var(--mint); border-color:var(--mint-2)}
/* Preferences page: hero, grouped tiles, heart toggles, sticky save */
.pf-top{display:flex; align-items:center; justify-content:space-between; padding:4px 0 2px}
.pf-top a{color:var(--green); font-weight:700}
.pf-top b{font-size:var(--fs-md)}
.pf-top span{width:44px}
.pf-hero{text-align:center; padding:14px 0 4px}
.pf-hero > svg{margin:0 auto 10px; display:block}
.pf-hero h1{font-size:var(--fs-display)}
.pf-hero .lead{max-width:46ch; margin:8px auto 0}
.pf-gh{font-size:var(--fs-xl); margin:30px 0 14px; text-align:center}
.pf-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:16px 10px}
.pfc{background:none; border:0; padding:0; font:inherit; cursor:pointer; display:flex; flex-direction:column; gap:8px; align-items:center; min-width:0}
.pfc-tile{position:relative; width:100%; aspect-ratio:1/1; border-radius:var(--r); background:var(--mint); display:flex; align-items:center; justify-content:center; transition:outline-color .15s}
.pfc-t1{background:var(--amber-soft)}
.pfc-t2{background:var(--rw-green-soft)}
.pfc-heart{
  position:absolute; top:8px; right:8px; width:30px; height:30px; border-radius:50%;
  background:#fff; display:flex; align-items:center; justify-content:center;
  box-shadow:0 1px 4px rgba(10,46,68,.18);
}
.pfc-heart svg{color:var(--faint); --duo:transparent}
.pfc.on .pfc-tile{outline:2.5px solid var(--green)}
.pfc.on .pfc-heart svg{color:var(--green-ink); --duo:var(--green)}
.pfc > b{font-size:var(--fs-sm); font-weight:650; color:var(--ink); text-align:center; line-height:1.25}
.pf-savebar{position:sticky; bottom:16px; margin-top:30px; z-index:30}
@media(max-width:760px){ .pf-savebar{bottom:calc(64px + env(safe-area-inset-bottom, 0px))} }

/* ---- FAQ accordion (/business/#faq, 28 Sep 2026) - native <details>, no JS ---- */
.faq{max-width:760px; margin:0 auto; border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{display:flex; justify-content:space-between; align-items:center; gap:16px; padding:18px 0; font-size:var(--fs-lg); font-weight:700; color:var(--ink); cursor:pointer; list-style:none}
.faq summary::-webkit-details-marker{display:none}
.faq summary svg{flex:none; width:18px; height:18px; color:var(--faint); transition:transform .2s}
.faq details[open] summary svg{transform:rotate(180deg)}
.faq details p{padding:0 0 18px; margin:0; font-size:var(--fs-md); line-height:var(--lh-body); color:var(--body); max-width:65ch}
@media (prefers-reduced-motion: reduce){.faq summary svg{transition:none}}

/* ---- Print (28 Sep 2026) ----
   People print a business page to keep the phone, address and hours on paper. Strip the site
   chrome, forms and fixed bars; keep the content in one column, black on white. */
@media print{
  .skip, .hdr, .catbar, .ftr, .tabbar, .actbar, .gallery, .cb-menu, .sugg, form, .pacts, .hc-report,
  .rev-lock, .btn, #btt, .cta-outer, .map iframe{display:none !important}
  body{background:var(--card); color:var(--ink)}
  .panel{box-shadow:none; border:1px solid var(--line); break-inside:avoid}
  .prof-grid{display:block; padding:0}
  .prof-grid .side{margin-top:16px}
  a{color:var(--ink); text-decoration:none}
  .crumb a{text-decoration:underline}
}

/* Leaflet's layer-switch button points at images/layers(-2x).png, which were never vendored with
   leaflet.js/css, so the button rendered as an empty white box. Inline icon instead (3-class
   selector so it beats leaflet.css's .leaflet-retina rule, which loads later). */
.leaflet-container .leaflet-control-layers .leaflet-control-layers-toggle{
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23333A3E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 2 10 5-10 5L2 7l10-5z'/%3E%3Cpath d='m2 12 10 5 10-5'/%3E%3Cpath d='m2 17 10 5 10-5'/%3E%3C/svg%3E");
  background-size:22px 22px;
}
