/* links/css/sections.css — IMP-004: the per-section CSS that used to ship as
 * a duplicated, uncacheable <style> block inside every one of the components
 * below, on every single page request. None of the rules in this file
 * interpolate any per-page value (no bizdetails-derived color/text/URL) —
 * every one was verified static before being moved here, which is what makes
 * a single shared, versioned, long-cached file safe: the SAME bytes are
 * correct for every page, so root .htaccess's mod_expires text/css rule
 * (~1 year, keyed on this exact URL including the ?v= query string) can
 * actually do its job. Genuinely per-page dynamic styling (owner colors via
 * the --color1/--color2/--bgcolor/--font1-.../--font2-... custom properties,
 * the page background) stays inline in links/index.php's own <style> block,
 * unchanged by this file.
 *
 * IMP-006 FIX: the line above used to read "--font1-*\/--font2-*" — inside a
 * /** ... *\/ comment, that exact substring is itself a literal "*\/", which
 * closes THIS comment right there, mid-sentence. Every byte of this file
 * from that point on (all ~100 rules, across every section listed below) was
 * then tokenized as ordinary CSS by every real browser: not a syntax error
 * that discards one bad rule and recovers, but a single corrupted selector
 * that keeps accumulating garbage across every subsequent comment/rule
 * boundary until the first stray "{" — discarding the ENTIRE stylesheet as
 * zero valid rules. Confirmed with a real browser (Chromium) against the
 * exact bytes this file has served since IMP-004: 0 parsed CSS rules with
 * the literal "*\/" in place, 100 with it removed. Nothing in this
 * repository's test suite would have caught this — PHPUnit renders HTML,
 * it never parses CSS in a browser engine — so every section this file
 * covers (navbar, enquiry-form, order-bar, gallery, videos, products,
 * services, contact-details, documents, payment-details, timings,
 * review-module) has been rendering with NONE of its own rules applied on
 * every live page since that commit. Never let "*\/" appear inside this
 * (or any) CSS comment's prose again, even unintentionally via a
 * hyphen/asterisk/slash sequence like the one above.
 *
 * Bump the ?v= query string in links/index.php any time this file's content
 * changes — same convention style.css's own header already documents (a
 * cache hit on the OLD bytes for up to a year otherwise).
 *
 * Source component for each section below, so a future edit knows where the
 * authoritative behaviour comment lives (most of these rules carry no
 * comment of their own here — the reasoning, where any exists, is still in
 * that component's PHP file, not duplicated into this CSS-only file):
 *   - links/components/navbar.php        (hamburger menu overlay)
 *   - links/components/enquiry-form.php  (free lead-capture form)
 *   - links/components/order-bar-shared.php (sticky "Order on WhatsApp" bar)
 *   - links/components/gallery.php       (lightbox modal + thumbnail grid)
 *   - links/components/videos.php        (video card + tap-to-play facade)
 *   - links/components/products.php      (product cards)
 *   - links/components/services.php      (service cards)
 *   - links/components/contact-details.php
 *   - links/components/documents.php
 *   - links/components/payment-details.php
 *   - links/components/timings.php
 *   - links/review-module.php            (Google review / private feedback)
 */

/* ── shared section/item headings (IMP-009) ───────────────────────────
 * Every links/components/*.php section title moved from `<h1
 * class="setctionTitle">` to `<h2 class="sectionTitle">` (the typo fixed in
 * the same rename), and every card's item heading moved from `<h5
 * class="card-title">` to `<h3 class="card-title">` -- one real <h1> per
 * page (the business name, links/index.php), sections at <h2>, items within
 * a section at <h3>, no more h1-to-h3/h5 skips.
 *
 * Both rules below exist ONLY to keep the RENDERED SIZE identical across
 * that tag change -- neither class carried a font-size rule before this
 * ticket, so the browser's own default UA/Bootstrap tag styling (h1: 2.5rem,
 * h5: 1.25rem) was what visitors actually saw. A class selector beats a bare
 * tag selector on specificity, so pinning the OLD tag's font-size here, on
 * the class, makes the semantic-only change byte-for-pixel invisible: same
 * font-size/weight/line-height/margins as before, regardless of which
 * heading level the markup now uses. Bootstrap 5.1.3's own heading defaults
 * (font-weight 500, line-height 1.2, margin-top 0) are unchanged by the tag
 * swap and are not re-stated here for that reason -- only font-size, which
 * genuinely differs per tag, needs pinning.
 */
/* UX-031: the 2.5rem pin above is retired. It was correct for IMP-009 (keep a
 * semantic h1->h2 rename pixel-invisible) and wrong for this ticket: at
 * --page-max the content column is 616px, so every section heading was 40px of
 * the word "Gallery" sitting above 13px content. §3.3 puts a section heading at
 * 17.5px/800; 1.5rem is where that lands legibly on a 390px phone.
 *
 * THIS RULE LIVES HERE, NOT IN style.css. Both files declare `.sectionTitle` at
 * the same specificity and links/index.php loads style.css FIRST — an
 * equal-specificity rule there loses to this file on source order and would
 * have silently done nothing. The preset files load after BOTH, so a preset can
 * still override this (theme7 does).
 *
 * The ::after tick is one of exactly two places the owner's own --color1
 * survives on the page (the other is #header's top rule in style.css). It is
 * DECORATION, never text: --color1 is unmeasurable owner data, and a decorative
 * tick that a #ffffff --color1 renders invisible is a plain heading, whereas
 * unmeasurable TEXT is an unreadable page the owner cannot diagnose. */
/* The editor calls font1 "Primary font — used for your business name and
 * section headings on your profile page". Only the business name was true:
 * nothing here declared a family, so every section heading inherited `body`'s
 * --font2-family and the owner's primary font appeared exactly once on the
 * whole page.
 *
 * THE WEIGHT COMES WITH THE FAMILY. Both, together, exactly as .font1
 * (links/style.css) does it for the <h1> — and the first attempt at this fix
 * took the family alone and kept §3.3's `font-weight: 800`, which put the
 * WRONG TYPEFACE on the page in a way that looked like the fix had not worked
 * at all.
 *
 * Why: links/index.php requests ONE weight of font1 from Google Fonts — the
 * one configured on the value ('Jura:600' -> 600; a bare 'Allerta Stencil' ->
 * none, i.e. 400). Asking for 800 when only a 400 face exists does not fall
 * back to another family (measured: the advance width stays the 400 face's
 * 185.25px, not sans-serif's 204px) — the browser SYNTHESISES bold by dilating
 * the 400 outlines. On an ordinary face that is merely a bit crude. On a
 * STENCIL face it closes the apertures that are the entire point of the
 * design, and 'Allerta Stencil' at 800 renders as an anonymous bold sans. The
 * business name, which uses --font1-weight and therefore a REAL face, sat
 * right above it looking completely different — the reported symptom.
 *
 * A weight that matches a loaded face is the only way to guarantee the owner
 * actually gets the typeface they picked. Requesting extra weights from Google
 * instead is not an option: the css2 API answers 400 for a weight a family
 * does not have, which would cost the page font1 entirely.
 *
 * The heading therefore carries its hierarchy on size (1.5rem against 13px
 * body copy), --ink-1, the tracking below and the accent tick — not on a
 * weight the font may not own.
 *
 * Placed on this rule rather than in style.css for the reason the comment above
 * gives: style.css loads first and would lose the tie. A preset may still
 * re-cut the heading (theme7 does) — none of them declare a family, so none of
 * them silently take the owner's font back off. */
.sectionTitle {
    font-family: var(--font1-family, inherit);
    font-weight: var(--font1-weight, 700);
    font-size: 1.5rem;
    letter-spacing: -0.02em;
    color: var(--accent);
    margin-bottom: 16px;
}

/* THE HOME OF ACCENT 2.
 *
 * Until this change --color2 was read by exactly ONE preset (theme10's gradient
 * sweeps) and exactly ZERO live pages used theme10 — so the 45 owners who had
 * deliberately picked a second colour had picked something that could not
 * appear anywhere in the product. Owner decision, 2026-08-15: the template
 * supplies structure, the colour section supplies colour.
 *
 * The tick is the right surface for it: every preset shares it (only theme8
 * opts out, and for a documented structural reason — its link stripe would be a
 * second, competing rule), it repeats under every section heading on the page,
 * and it is pure DECORATION, so a gradient here can never be half of an
 * unmeasurable text pair. That is also why the sweep is not on the buttons: a
 * gradient fill cannot be contrast-checked against its label the way the flat
 * --accent/--on-accent pair can.
 *
 * `var(--accent-2, var(--accent))` collapses the sweep to a flat accent bar for
 * an owner who chose only one colour — the previous appearance exactly, with no
 * second branch to keep in step.
 *
 * Was `var(--color1, ...)`, the RAW stored value: on the 145 pages carrying the
 * #000333 factory default that painted a near-black tick under headings whose
 * page accent was the preset's. It reads --accent now, so it agrees with every
 * other accent surface. */
.sectionTitle::after {
    content: "";
    display: block;
    width: 32px;
    height: 3px;
    margin-top: 8px;
    border-radius: 2px;
    background: linear-gradient(
        90deg,
        var(--accent) 0%,
        var(--accent-2, var(--accent)) 100%
    );
}

.card-title {
    font-size: 1.25rem;
}

/* ── navbar.php ─────────────────────────────────────────────────────── */
.menupoweredby {
    color: #aaa;
    position: fixed;
    bottom: 0px;
    margin: 0 auto;
    width: 100vw;
}

/* UX-030 P-5: the second of the two "BizGo.in" credit links (this one lives
   inside the overlay menu). Same reasoning as #credits a in style.css — see
   that rule for why this is inline-flex + min-height and not padding. */
.menupoweredby a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 8px;
    vertical-align: middle;
}

/* IMP-009: the overlay menu's visible close button. #menu is position:fixed,
   so this absolute box positions relative to it, top-right, over the dark
   #000000f0 overlay -- white to stay legible against that background, same
   glyph/size language as .bizgo-qr-close/.paymentQrModalClose elsewhere in
   this file's own overlay-close convention, just re-colored for this one's
   dark backdrop. */
/* UX-030 P-5: was 28x34 as measured — a 32px glyph with no box of its own.
   The flex centring is what lets the button be 48x48 without the glyph
   drifting off centre. */
.menuCloseBtn {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 10;
    background: none;
    border: none;
    font-size: 32px;
    line-height: 1;
    cursor: pointer;
    color: #fff;
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.mainWrapper {
    overflow-x: hidden;
}

#menu {

    height: 100vh;
    margin: 0px 0 0 -250px;
    /* UX-031: --overlay-bg. Opaque, not #000000f0 — the 6% of the page that
       bled through was the owner's flood colour, which is exactly what this
       ticket removes everywhere else. */
    background: var(--overlay-bg);
    -webkit-font-smoothing: antialiased;
    position: fixed;
    right: calc(0px - 100vw);
    width: 100vw;
    transition: all 0.3s ease;
    z-index: 9;
    overflow: scroll;
}

#menu-list {
    list-style-type: none;
    padding: 50px;

}

#menu-list li {
    padding: 10px 0;
    font-size: 18px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}


#menu a {
    text-decoration: none;
    color: #fff;

    transition: color 0.3s ease;
}

#menu a:hover {
    color: tomato;
}

/* ── enquiry-form.php ───────────────────────────────────────────────── */
#enquiryform {
  padding-top: 24px;
  padding-bottom: 24px;
}

.enquiryFormBox {
  max-width: 500px;
}

/* UX-031: #ff8a80 measured 2.20:1 on a white panel — a form's own error
   message, unreadable. --error/--success are the measured tokens. */
.enquiryFormBox .successMsg {
  color: var(--success);
}

.enquiryFormBox .errorMsg {
  color: var(--error);
}

/* IMP-041 (item 1, lazy-load): the skeleton placeholder shown before the
 * real form loads (links/components/enquiry-form.php's default/non-fragment
 * mode) — reserves the real form's approximate footprint (3 field bars + a
 * button bar, ~208px) so swapping in the real form on load causes no layout
 * shift, and stays visible as a real, focusable placeholder for a visitor on
 * a slow connection who taps/scrolls past before the fetch resolves. */
.enquiryFormSkeleton {
  cursor: pointer;
}

.enquiryFormSkeletonBar {
  height: 38px;
  margin-bottom: 0.5rem;
  border-radius: 4px;
  background: rgba(127, 127, 127, 0.18);
}

.enquiryFormSkeletonBarTall {
  height: 70px;
}

.enquiryFormSkeletonBtn {
  width: 140px;
  height: 38px;
  border-radius: 4px;
  background: rgba(127, 127, 127, 0.3);
}

/* ── order-bar-shared.php ───────────────────────────────────────────── */
.bizgoOrderBar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1050;
  background: var(--panel);
  color: var(--ink-1);
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
  max-height: 45vh;
  flex-direction: column;
}

.bizgoOrderBarItems {
  overflow-y: auto;
  padding: 8px 12px;
}

.bizgoOrderBarRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}

.bizgoOrderBarRow:last-child {
  border-bottom: none;
}

.bizgoOrderBarName {
  flex: 1 1 auto;
  font-size: 14px;
  color: var(--ink-1);
  overflow-wrap: anywhere;
}

.bizgoOrderBarPrice {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--ink-2);
  white-space: nowrap;
}

.bizgoOrderBarQtyWrap {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

.bizgoOrderBarQtyBtn {
  width: 26px;
  height: 26px;
  border: 1px solid var(--line);
  background: var(--chip);
  color: var(--ink-1);
  border-radius: 4px;
  cursor: pointer;
  line-height: 1;
}

.bizgoOrderBarQty {
  min-width: 18px;
  text-align: center;
  font-size: 14px;
}

.bizgoOrderBarRemoveBtn {
  flex: 0 0 auto;
  border: none;
  background: transparent;
  color: var(--error);
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
}

.bizgoOrderBarFooter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-top: 1px solid var(--line);
  gap: 10px;
}

.bizgoOrderBarSummary {
  font-size: 13px;
  color: var(--ink-2);
}

/* UX-031: was var(--color1) under var(--bgcolor) — two unrelated pieces of
   owner data, the same unmeasurable pairing .modalButtons carried. */
.bizgoOrderBarSendBtn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: var(--radius-pill);
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.bizgoOrderBarSendBtn:active {
  opacity: 0.85;
}

/* ── gallery.php ────────────────────────────────────────────────────── */
.galleryContainer {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  padding: 20px;
}

@media (min-width: 576px) {
  .galleryContainer {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* UX-030 P-1 fallout: this grid keys off the VIEWPORT, but since P-1 the
   content column is capped at --page-max (640px) at every viewport above it —
   so "≥992px viewport" no longer means "lots of horizontal room". Four across
   a ~600px column is a ~140px thumbnail; three is ~193px. The 4-across rule is
   removed rather than rebreakpointed because there is now no viewport at which
   this grid gets wider than 3 x 193px.

   ⚠️ UX-031: several grids in links/ have this same shape (Bootstrap's
   col-md-* in products/services/videos, which are viewport media queries too).
   If a preset ever widens --page-max, re-check all of them together. */

.galleryCol {
  overflow: hidden;
  border-radius: 8px;
}

/* IMP-047 (Defect 6): scoped to #imageModal, not the bare `.modal` class —
   see gallery.php's own (removed) copy of this comment for the full
   reasoning; unchanged by this file's move. */
#imageModal {
  top: 20%;
}

.imageModalHeader {
  display: block;
}

.imageModalHeader button.close {
  float: right;
}

.galleryCounter {
  display: inline-block;
  padding: 4px 10px;
  font-size: 0.9rem;
  line-height: 1.6;
  opacity: 0.75;
}

#galleryModalBody {
  position: relative;
}

.galleryNav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1.1rem;
  line-height: 40px;
  cursor: pointer;
}

.galleryNav:hover {
  background: rgba(0, 0, 0, 0.7);
}

.galleryPrev {
  left: 10px;
}

.galleryNext {
  right: 10px;
}

.galleryCaption {
  margin: 0;
  padding: 10px 16px 14px;
  text-align: center;
  font-size: 0.95rem;
}

.thumbnail {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  cursor: pointer;
  transition: transform 0.2s;
}

.thumbnail:hover {
  transform: scale(1.1);
}

/* ── videos.php ─────────────────────────────────────────────────────── */
#videosContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
}

#videosContainer .card-body {
    background: transparent;
}

.embed-responsive {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    overflow: hidden;
    min-height: 200px;
    aspect-ratio: 16 / 9;
}

.embed-responsive iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.videoFacade {
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: #000;
    cursor: pointer;
}

.videoPoster {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.videoPlayIcon {
    position: relative;
    width: 68px;
    height: 48px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.6);
    transition: background 0.2s;
}

.videoFacade:hover .videoPlayIcon,
.videoFacade:focus-visible .videoPlayIcon {
    background: #f00;
}

.videoPlayIcon::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-style: solid;
    border-width: 10px 0 10px 17px;
    border-color: transparent transparent transparent #fff;
}

/* ── products.php ───────────────────────────────────────────────────── */
#productsContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
    overflow: hidden;
}

#productsContainer .card-body {
    background: transparent;
}

/* UX-030 P-1 fallout: `justify-content: space-between` with `height: 100%` and
   no wrapping put the price and the Enquiry/Add buttons on one unbreakable
   line. In the 640px column a product card is ~295px wide, the price wraps to
   two lines, and the button rode straight over it — reproduced in a browser at
   1440px on `webglits`, where "₹1299" and "Enquiry" overlapped outright.
   Wrapping + a gap + centring is what makes this row survive any card width;
   `height: auto` stops the row stretching to the card body and dragging the
   button's vertical centre with it. */
.priceWrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 8px;
    height: auto;
}

.priceWrapper p {
    font-size: x-large;
    margin: 4px !important
}

.priceWrapper p del {
    font-size: medium;
}

/* UX-030 P-1 fallout: products and services are Bootstrap `col-md-4`, i.e.
   three across from a 768px VIEWPORT — which, since the content column is
   capped at --page-max, means ~190px cards at every desktop width instead of
   the ~356px they used to get at 1440px. Two across (~295px) is what the card
   actually needs: an image, a title, a description, a price and up to two
   44px buttons. Below 576px both stay one across, exactly as before.

   Scoped to these two containers by id, never to `.col-md-4` at large — the
   same class is used elsewhere in links/ where three across is still right. */
@media (min-width: 576px) {
    #productsContainer > .col-md-4,
    #servicesContainer > .col-md-4 {
        flex: 0 0 auto;
        width: 50%;
    }
}

/* ── services.php ───────────────────────────────────────────────────── */
#servicesContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
    overflow: hidden;
}

#servicesContainer .card-body {
    background: transparent;
}

/* ── contact-details.php ────────────────────────────────────────────── */
#contactdetails {
  padding-top: 24px;
  padding-bottom: 24px;
}

/* UX-031: `var(--background1)` was a typo for a property nothing ever defines,
   so this declaration has always been invalid-at-computed-value-time and the
   colour actually came from inheritance. Named explicitly now. */
.contactLink {
  text-decoration: none;
  color: var(--ink-1);
  padding: 10px 30px;
  font-size: large;
}

.contactTitle {
  text-align: center;
}

/* IMP-009: the contact person's name moved from `<h1 class="contactTitle">`
   to `<h3 class="contactPersonName">` (an item within the contactdetails
   section, not a second page-level h1) -- given its own class, rather than
   staying h3.contactTitle alongside the designation's own (unchanged)
   h3.contactTitle, because both would otherwise be the exact same
   tag+class pair with no way to keep the name visually larger than the
   designation beneath it. font-size/font-weight/line-height/margin-bottom
   reproduce Bootstrap 5.1.3's own h1 defaults (2.5rem/500/1.2/0.5rem) that
   applied here uncontested before this rename -- text-align and the 30px
   top margin are this rule's own pre-existing values, carried over
   unchanged from h1.contactTitle. */
.contactPersonName {
  text-align: center;
  margin-top: 30px;
  margin-bottom: 0.5rem;
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.2;
}

/* ── documents.php ──────────────────────────────────────────────────── */
#documentDetailsContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
}

#documentDetailsContainer .card-body {
    background: transparent;
}

/* ── payment-details.php ────────────────────────────────────────────── */
#paymentDetailsContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
    overflow: hidden;
}

#paymentDetailsContainer .card-body {
    background: transparent;
}

/* IMP-006: tap-to-pay button + generated QR + copy buttons. Only ever
   emitted for a card that has a UPI id (payment-details.php's own
   $paymentNeedsScript gate) — a legacy image-only/bank-blob-only page never
   reaches any of these classes at all. */
.paymentQrBox {
  position: relative;
  width: 100%;
  max-width: 200px;
  margin: 0 auto;
  cursor: pointer;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
}

.paymentQrFallbackImg {
  display: block;
  width: 100%;
  height: auto;
}

.paymentQrCanvasWrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100px;
}

.paymentQrCanvasWrap canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

.paymentUpiRow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.paymentUpiValue {
  font-size: 0.9rem;
  word-break: break-all;
}

/* UX-030 P-5: measured 54x28. */
.paymentCopyBtn {
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  border-radius: 20px;
  padding: 4px 12px;
  font-size: 0.8rem;
  line-height: 1.4;
  cursor: pointer;
  white-space: nowrap;
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.paymentCopyBtnDone {
  opacity: 0.7;
}

/* Shown by default (desktop/mouse gets the QR as the primary affordance —
   the task brief's own "desktop shows the QR instead"); the media query
   below reveals it on a touch-primary device instead. No JS involved in
   this decision either way — see payment-details.php's own header for why
   the underlying <a href="upi://…"> always exists in the markup
   regardless of which device shows it. */
/* UX-030 P-5: measured 133x42 — two pixels short of the floor. */
.paymentUpiPayBtn {
  display: none;
  margin-top: 12px;
  padding: 10px 18px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  min-height: 44px;
}

@media (hover: none) and (pointer: coarse) {
  .paymentUpiPayBtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* structured bank fields (IMP-006) */
.paymentBankRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
}

.paymentBankRow:last-of-type {
  border-bottom: none;
}

.paymentBankRowLabel {
  flex: 0 0 auto;
  font-size: 0.85rem;
  opacity: 0.8;
}

.paymentBankRowValue {
  flex: 1 1 auto;
  margin-right: 8px;
  font-size: 0.9rem;
  text-align: right;
  word-break: break-all;
}

.paymentBankLegacyNote {
  margin-top: 10px;
  font-size: 0.85rem;
  opacity: 0.85;
}

/* enlarge-QR modal — its OWN namespace (paymentQr*), deliberately not a
   reuse of .bizgo-qr-* (save-share.php, GROW-013) even though the two look
   alike: that file's own header documents "duplicated rather than shared
   so this and the QR modal can each be touched independently without one
   task's edit risking the other's tested markup" — same reasoning applies
   here, one ticket later. */
.paymentQrOverlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
  z-index: 999999;
  align-items: center;
  justify-content: center;
  padding: 20px;
  box-sizing: border-box;
}

.paymentQrModalBox {
  background: var(--panel);
  color: var(--ink-1);
  border-radius: var(--radius-inner);
  padding: 24px;
  max-width: 380px;
  width: 100%;
  text-align: center;
  position: relative;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}

.paymentQrModalClose {
  position: absolute;
  top: 4px;
  right: 10px;
  background: none;
  border: none;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  color: var(--ink-2);
}

.paymentQrModalCanvasWrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 240px;
}

.paymentQrModalCanvasWrap canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

/* ── timings.php ────────────────────────────────────────────────────── */
#timingsDetailsContainer .card {
    background: transparent;
    border: 1px solid var(--line);
    margin: 10px;
    border-radius: 10px;
}

#timingsDetailsContainer .card-body {
    background: transparent;
}

#timingsDetailsContainer .list-group-item {
    background: transparent;
    border: none;
    padding: 5px;
    color: var(--ink-2);
}

/* UX-031: `opacity: 0.75` is removed, not re-tuned. Element opacity composites
   AFTER colour resolution, so it silently multiplies away part of a ratio this
   ticket measures — a token that reads 5.19:1 in the table renders at ~3.9:1
   through it. --ink-3 IS the muted step; it does not need dimming on top. */
#timings .timingsStatus {
    color: var(--ink-3);
    font-size: 14px;
    margin: 0 0 4px;
}

#timings .timingsStatusOpen {
    color: var(--success);
    font-weight: 600;
}

/* The "today" marker in the timings list. Was `var(--color1)` with NO fallback
   at all — so on the 9 pages storing an empty colour1 the declaration was
   invalid and there was no rule, and on the 145 still holding the #000333
   factory default it painted a near-black bar next to preset-coloured
   everything else. --accent is the page's resolved accent either way. */
#timingsDetailsContainer .timingsToday {
    font-weight: 700;
    border-left: 2px solid var(--accent);
    padding-left: 8px;
}

/* ── review-module.php ──────────────────────────────────────────────── */
/* UX-030 P-6: `.googleReiviewsImage` (sic) styled a 200x90 raster of Google's
   own logo lockup — links/images/google-reviews.png, 62 KB, on every page
   with a review link, pasted at a fixed 200px regardless of DPR. Two problems
   in one asset: reproducing Google's logo is a brand-guideline exposure this
   product does not need, and at 2x it was visibly soft. The ticket allows an
   official SVG OR dropping the wordmark; this drops it — the CTA underneath
   already names Google in the owner's own words, and naming a service in
   running text is not a use of its mark. The rule is left in place, matching
   nothing, so any stale render of the old markup degrades to an unstyled
   <img> rather than a 200px one pinned under a -30px margin. */
.googleReiviewsImage {
  width: 200px;
  margin: 0 auto;
  display: block;
  margin-top: -30px;
  margin-bottom: 20px;
}

/* The review card's whole call to action — and now it LOOKS like one.

   It was `display: block; color: var(--ink-1); text-decoration: none` wrapping
   an <h3>: unstyled dark text at heading size, i.e. indistinguishable from a
   section title. Directly beneath it sat "Send us private feedback" as a real
   bordered Bootstrap button. So the card asked visitors to press the secondary
   action and read the primary one — the entire point of the panel (sending
   happy customers to Google) presented as a caption.

   It is the accent/on-accent pair, the same one .modalButtons and
   .bizgoOrderBarSendBtn use, so it moves with the preset AND with the owner's
   chosen palette (links/lib/accent.php) instead of being a third opinion about
   what a button looks like on this page. `min-height: var(--tap-min)` is
   UX-030 P-5's 44px floor; it did not previously apply here because a block
   link had no height of its own at all. */
.reviewCtaLink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: 10px 24px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.reviewCtaLink:hover,
.reviewCtaLink:focus {
  color: var(--on-accent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

/* The quiet counterpart. Deliberately NOT a second filled button: there is one
   primary action on this card and the alternative should read as an offer, not
   as a competing choice. Bootstrap's .btn-outline-secondary (what this
   replaces) is a fixed grey with no idea which preset it is on — it measured
   near-invisible on the four dark ones. */
.reviewSecondaryBtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: 8px 16px;
  border: none;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink-2);
  font-size: 0.9rem;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.reviewSecondaryBtn:hover,
.reviewSecondaryBtn:focus {
  color: var(--ink-1);
  background: var(--chip);
  text-decoration: none;
}

/* `fill` lives here, not as a presentation attribute in review-module.php: an
   attribute cannot read a custom property (var() is CSS), and keeping the
   colour in the stylesheet is what lets UX-031 re-cut it per preset. `fill`
   is inherited in SVG, so declaring it on the root <svg> reaches the <use>
   shadow content and therefore all five stars.

   UX-031: --warning is a TEXT-safe amber on a light panel (8.6:1) and each of
   the four dark presets lifts it to its own value, so the star row moves with
   the preset rather than being a fixed dark-amber that vanishes on a dark card. */
.googleReviewStars {
  display: block;
  margin: 0 auto 12px;
  width: 132px;
  height: 24px;
  fill: var(--warning);
}

/* A button LABEL now, not a heading. 1.25rem was section-title size — the
   single biggest reason this control read as a title — and the bottom margin
   was spacing between a heading and the content under it, which a label inside
   a flex button has no use for. */
.reviewCta {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
}

/* UX-030: the review panel, retuned to the §3 language — 24px radius, hairline
   in --line rather than the old #999, --panel ground, soft lift instead of a
   hard border. This is the card's whole visual anchor now that the star badge
   is gone (P-8; see links/review-module.php for why it was removed rather than
   rebuilt). */
.reviewmodal {
  border: 1px solid var(--line);
  border-radius: var(--radius-panel);
  padding: 24px 20px 20px;
  text-align: center;
  background-color: var(--panel);
  box-shadow: var(--shadow-md);
  position: relative;
}

/* UX-030 P-8: .reviewTopHeart's markup is deleted from review-module.php, so
   these match nothing on a fresh render. Kept, neutered, rather than deleted
   outright so any stale render of the old span degrades to nothing rather
   than to the raw 32px glyph and its grey ::after disc. */
.reviewTopHeart {
  display: none;
}

.reviewTopHeart::after {
  content: none;
}


/* UX-031: #777 on a white panel measures 4.48:1 — a real, shipped AA failure,
   0.02 under the bar, found by measuring rather than by eye. --ink-3 is 5.19:1
   on the same panel and moves with the preset. */
.reviewmodal p {
  font-weight: 400;
  font-size: 12px;
  color: var(--ink-3);
}

.hidden {
  display: none !important;
}

/* UX-031: `red` (#f00) measures 4.00:1 on white — the global error style, on
   every page, below AA. `green` (#008000) passed at 5.13:1 but is not a token
   and does not move with a dark preset. */
.errorMsg {
  color: var(--error) !important;
}

.successMsg {
  color: var(--success) !important;
}
