/* ==========================================================================
   Aayam Technovations — Forms, modal and page-scoped rules
   ========================================================================== */

/* ==========================================================================
   Legacy bridge
   Applies only to pages still rendering the original template markup
   (body.ay-legacy). These sheets load before the ay-* layer, so plain
   two-class selectors are enough to win -- no !important required.
   ========================================================================== */

/* responsive.css offsets .content-wrapper by 128px to clear the OLD absolutely
   positioned header. The new header sits in normal flow, so that offset is now
   just a white gap under it. */
.ay-legacy .content-wrapper { margin-top: 0; }

/* The old markup relied on the previous header/footer for horizontal padding
   at small sizes; keep legacy sections clear of the viewport edge. */
.ay-legacy .breadcrumb-wrap { background-attachment: scroll; }

/* ==========================================================================
   Enquiry form
   ========================================================================== */
.ay-form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ay-4);
}
.ay-form__grid--compact { grid-template-columns: minmax(0, 1fr); }
.ay-field--full { grid-column: 1 / -1; }

@media (max-width: 575px) {
  .ay-form__grid { grid-template-columns: minmax(0, 1fr); }
}

.ay-form__note {
  margin-top: var(--ay-3);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  text-align: center;
}
.ay-on-invert .ay-form__note { color: var(--ay-text-on-invert-muted); }
/* --------------------------------------------------------------------------
   Quote wizard

   Three steps in one form. Only the active step is shown; the rest stay in the
   DOM so going Back never loses an answer. Nothing is hidden until JS marks the
   form ready, so with scripting off the whole form is one long page that still
   submits.
   -------------------------------------------------------------------------- */
.ay-wiz__step + .ay-wiz__step { margin-top: var(--ay-6); }

.ay-wiz.is-ready .ay-wiz__step { display: none; }
.ay-wiz.is-ready .ay-wiz__step.is-active { display: block; margin-top: 0; }

.ay-wiz__head { margin-bottom: var(--ay-4); }
.ay-wiz__head h4 {
  margin: 0;
  font-size: var(--ay-fs-xl);
  font-weight: var(--ay-fw-semi);
  line-height: 1.25;
  color: var(--ay-text);
}
.ay-wiz__head p {
  margin: var(--ay-1) 0 0;
  font-size: var(--ay-fs-sm);
  color: var(--ay-text-muted);
}
/* Each step moves focus to its heading so a screen reader announces the new
   step. The heading carries tabindex="-1", so it can never be reached by Tab
   and this outline would only ever appear for that programmatic focus. */
.ay-wiz__head h4:focus { outline: none; }

.ay-on-invert .ay-wiz__head h4 { color: var(--ay-text-on-invert); }
.ay-on-invert .ay-wiz__head p  { color: var(--ay-text-on-invert-muted); }

/* Only fields stacked directly in a step need this. Inside .ay-form__grid
   the grid gap already spaces them, and a margin here pushed the second
   column down so "Mobile number" sat lower than "Full name". */
.ay-wiz__step > .ay-field + .ay-field { margin-top: var(--ay-4); }

/* --- Progress ------------------------------------------------------------ */
.ay-wiz__progress { margin-bottom: var(--ay-5); }

.ay-wiz__dots {
  display: flex;
  align-items: center;
  gap: var(--ay-2);
  margin-bottom: var(--ay-3);
}
.ay-wiz__dot {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  white-space: nowrap;
}
.ay-wiz__dot + .ay-wiz__dot { margin-left: var(--ay-3); }
.ay-wiz__dot b {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--ay-border);
  background: var(--ay-white);
  font-size: 11px;
  font-weight: var(--ay-fw-bold);
  color: var(--ay-text-muted);
  transition: all var(--ay-dur-1) var(--ay-ease);
}
/* Current step: filled. Steps already answered: outlined accent, so progress
   reads at a glance without a legend. */
.ay-wiz__dot.is-current b { background: var(--ay-accent); border-color: var(--ay-accent); color: #fff; }
.ay-wiz__dot.is-current    { color: var(--ay-text); font-weight: var(--ay-fw-semi); }
.ay-wiz__dot.is-done b     { background: var(--ay-red-50); border-color: var(--ay-accent); color: var(--ay-accent-text); }

.ay-wiz__bar {
  height: 4px;
  border-radius: var(--ay-r-pill);
  background: var(--ay-surface-2);
  overflow: hidden;
}
.ay-wiz__bar i {
  display: block;
  height: 100%;
  width: 33.33%;
  border-radius: inherit;
  background: var(--ay-accent);
  transition: width var(--ay-dur-2) var(--ay-ease);
}

.ay-wiz__count {
  margin: var(--ay-2) 0 0;
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
}

.ay-on-invert .ay-wiz__dot   { color: var(--ay-text-on-invert-muted); }
.ay-on-invert .ay-wiz__dot b { background: rgba(255,255,255,.06); border-color: var(--ay-border-invert); color: var(--ay-text-on-invert-muted); }
.ay-on-invert .ay-wiz__dot.is-current { color: var(--ay-text-on-invert); }
.ay-on-invert .ay-wiz__bar   { background: rgba(255,255,255,.12); }
.ay-on-invert .ay-wiz__count { color: var(--ay-text-on-invert-muted); }

/* Below 480px the step names would wrap the row; the numbers and the bar carry
   the meaning on their own. */
@media (max-width: 479px) {
  .ay-wiz__dot span { display: none; }
  .ay-wiz__dot + .ay-wiz__dot { margin-left: var(--ay-2); }
}

/* The full-width form keeps the large forward action; it sits in a hero or a
   modal with room for it. */
.ay-wiz:not(.ay-wiz--compact) .ay-wiz__nav [data-ay-next],
.ay-wiz:not(.ay-wiz--compact) .ay-wiz__nav [type="submit"] {
  padding: 17px 34px;
  font-size: var(--ay-fs-base);
}

/* --- Compact variant -----------------------------------------------------
   The class was on the form already but styled nothing, so this form looked
   identical to the full-width one while sitting in a column half the width.
   Everything here is a size down. */
.ay-wiz--compact .ay-wiz__nav { margin-top: var(--ay-4); gap: var(--ay-2); }
.ay-wiz--compact .ay-wiz__nav .ay-btn {
  padding: 11px 18px;
  font-size: var(--ay-fs-sm);
}
.ay-wiz--compact .ay-wiz__nav .ay-btn .las { font-size: 1em; }

/* --- Step navigation ----------------------------------------------------- */
.ay-wiz__nav {
  display: flex;
  align-items: center;
  gap: var(--ay-3);
  margin-top: var(--ay-5);
}
/* Back sits left, the forward action right, however many buttons there are. */
.ay-wiz__nav > [data-ay-back] { margin-right: auto; }
.ay-wiz__nav > :only-child    { width: 100%; justify-content: center; }

@media (max-width: 479px) {
  /* Stack, forward action on top: it is the one being reached for. */
  .ay-wiz__nav { flex-direction: column-reverse; align-items: stretch; gap: var(--ay-2); }
  .ay-wiz__nav > * { width: 100%; justify-content: center; }
  .ay-wiz__nav > [data-ay-back] { margin-right: 0; }
}

/* --------------------------------------------------------------------------
   Choice pills (single-select) and service chips (multi-select)

   Both are labels wrapping a real input, so keyboard and screen readers get
   native radio/checkbox behaviour and the visual is entirely CSS.
   -------------------------------------------------------------------------- */
.ay-pills,
.ay-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ay-2);
}

.ay-pill,
.ay-chip-opt {
  position: relative;
  margin: 0;
  cursor: pointer;
}

.ay-pill input,
.ay-chip-opt input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ay-pill > span,
.ay-chip-opt > span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 10px var(--ay-4);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r-pill);
  background: var(--ay-white);
  font-size: var(--ay-fs-sm);
  line-height: 1.3;
  color: var(--ay-text);
  transition: all var(--ay-dur-1) var(--ay-ease);
}
.ay-pill:hover > span,
.ay-chip-opt:hover > span { border-color: var(--ay-slate-400); }

/* The marker: a ring for single-select, a tick box for multi-select. */
.ay-pill > span::before {
  content: "";
  flex: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid var(--ay-slate-400);
  transition: all var(--ay-dur-1) var(--ay-ease);
}
.ay-chip-opt > span::before {
  content: "";
  flex: none;
  width: 15px;
  height: 15px;
  border-radius: 4px;
  border: 2px solid var(--ay-slate-400);
  transition: all var(--ay-dur-1) var(--ay-ease);
}

.ay-pill input:checked ~ span,
.ay-chip-opt input:checked ~ span {
  border-color: var(--ay-accent);
  background: var(--ay-red-50);
  color: var(--ay-red-700);
  font-weight: var(--ay-fw-medium);
  box-shadow: inset 0 0 0 1px var(--ay-accent);
}
.ay-pill input:checked ~ span::before {
  border-color: var(--ay-accent);
  background: var(--ay-accent);
  box-shadow: inset 0 0 0 3px var(--ay-white);
}
.ay-chip-opt input:checked ~ span::before {
  border-color: var(--ay-accent);
  background: var(--ay-accent);
  /* A tick drawn with a border, so no icon font is needed. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.5 3.5L13 5'/%3E%3C/svg%3E");
  background-size: 11px 11px;
  background-position: center;
  background-repeat: no-repeat;
}

.ay-pill input:focus-visible ~ span,
.ay-chip-opt input:focus-visible ~ span { box-shadow: var(--ay-focus); }

/* The whole group is flagged when nothing was chosen. */
.ay-pills.is-invalid > .ay-pill > span,
.ay-chips.is-invalid > .ay-chip-opt > span { border-color: var(--ay-accent); }

.ay-on-invert .ay-pill > span,
.ay-on-invert .ay-chip-opt > span {
  background: rgba(255, 255, 255, .06);
  border-color: var(--ay-border-invert);
  color: var(--ay-text-on-invert);
}
.ay-on-invert .ay-pill input:checked ~ span,
.ay-on-invert .ay-chip-opt input:checked ~ span {
  background: rgba(234, 0, 0, .24);
  border-color: var(--ay-accent);
  color: #fff;
}

/* On a phone the options go full width rather than wrapping into ragged rows. */
@media (max-width: 575px) {
  .ay-pills,
  .ay-chips { flex-direction: column; align-items: stretch; }
  .ay-pill > span,
  .ay-chip-opt > span { width: 100%; }
}

/* A quieter qualifier next to a label ("Optional", "Select all that apply"). */
.ay-label__aside {
  font-weight: var(--ay-fw-normal);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  margin-left: var(--ay-2);
}
.ay-on-invert .ay-label__aside { color: var(--ay-text-on-invert-muted); }
.ay-formcard {
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r-lg);
  padding: clamp(24px, 3.4vw, 40px);
  box-shadow: var(--ay-shadow-1);
}
.ay-formcard__head { margin-bottom: var(--ay-5); }
.ay-formcard__head p { color: var(--ay-text-muted); margin-top: var(--ay-2); font-size: var(--ay-fs-sm); }

/* ==========================================================================
   Modal skin (Bootstrap 5 structure, ay- presentation)
   ========================================================================== */
/* Sized to fit the first view without page scrolling. The dialog is capped to
   the viewport so that on unusually short screens the form column scrolls
   internally rather than the dialog being clipped. */
.ay-modal .modal-dialog {
  max-width: min(1040px, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
}
.ay-modal .ay-modal__content {
  position: relative;
  border: 0;
  border-radius: var(--ay-r-lg);
  overflow: hidden;
  box-shadow: var(--ay-shadow-3);
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
}

.ay-modal__grid {
  display: grid;
  grid-template-columns: 40% 60%;
  min-height: 0;
  max-height: inherit;
}

/* --- 30% branded panel -------------------------------------------------- */
.ay-modal__aside {
  position: relative;
  isolation: isolate;
  background: var(--ay-ink);
  color: var(--ay-text-on-invert);
  overflow: hidden;
}
.ay-modal__aside > img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
}
/* Mostly ink so the copy stays legible. The red glow is pushed to the lower
   right, clear of the reversed logo at the top left -- sitting under the logo
   it washed out the wordmark. */
.ay-modal__aside::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(95% 55% at 108% 88%, rgba(234, 0, 0, .34) 0%, rgba(234, 0, 0, 0) 62%),
    linear-gradient(168deg, rgba(4, 17, 21, .92) 0%, rgba(4, 17, 21, .95) 50%, rgba(4, 17, 21, .99) 100%);
}
/* A thin brand edge where the panel meets the form. */
.ay-modal__aside::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0; right: 0;
  width: 3px;
  background: var(--ay-red);
  z-index: 1;
}
.ay-modal__aside-inner {
  height: 100%;
  padding: var(--ay-6) var(--ay-5);
  display: flex;
  flex-direction: column;
  gap: var(--ay-5);
}
.ay-modal__aside-logo { height: 40px; width: auto; flex: none; }
.ay-modal__aside-body { margin-top: auto; }
.ay-modal__aside h3 {
  color: #fff;
  font-size: var(--ay-fs-xl);
  margin-bottom: var(--ay-2);
}
.ay-modal__aside p {
  font-size: var(--ay-fs-sm);
  color: var(--ay-text-on-invert-muted);
}

.ay-modal__points { display: grid; gap: var(--ay-2); }
.ay-modal__points li {
  display: flex;
  align-items: flex-start;
  gap: var(--ay-2);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-on-invert);
  line-height: 1.45;
}
.ay-modal__points i {
  flex: none;
  width: 16px; height: 16px;
  margin-top: 2px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--ay-red);
  color: #fff;
  font-size: .6rem;
}

.ay-modal__aside-wa {
  display: inline-flex;
  align-items: center;
  gap: var(--ay-2);
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-semi);
  color: #fff;
  padding-top: var(--ay-3);
  border-top: 1px solid var(--ay-border-invert);
}
.ay-modal__aside-wa i { color: var(--ay-wa); font-size: 1.15rem; }
.ay-modal__aside-wa:hover { color: var(--ay-wa); }

/* --- 70% form panel ----------------------------------------------------- */
/* padding-top clears the absolutely positioned close button, which otherwise
   sits on top of the second field in the first row. */
.ay-modal__main {
  padding: 58px var(--ay-6) var(--ay-6);
  overflow-y: auto;             /* fallback only — the form is sized to fit */
  overscroll-behavior: contain;
  max-height: inherit;
}
/* The branded panel already carries the heading, so the form column starts
   straight at the first field — that removed height is what makes the dialog
   fit short viewports without an inner scrollbar. */

.ay-modal__close {
  position: absolute;
  top: var(--ay-4);
  right: var(--ay-4);
  z-index: 3;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--ay-surface);
  color: var(--ay-ink);
  font-size: 1.1rem;
  transition: background-color var(--ay-dur-1) var(--ay-ease), color var(--ay-dur-1) var(--ay-ease);
}
.ay-modal__close:hover { background: var(--ay-red); color: #fff; }
.ay-modal__close:focus-visible { outline: none; box-shadow: var(--ay-focus); }

/* Compact field metrics, scoped to the modal so the full-size Contact page and
   product-detail forms keep their roomier spacing. */
.ay-modal .ay-form__grid { gap: 10px; }
.ay-modal .ay-field { gap: 4px; }
.ay-modal .ay-label { font-size: var(--ay-fs-xs); }
.ay-modal .ay-input,
.ay-modal .ay-select,
.ay-modal .ay-textarea { padding: 9px 14px; }
.ay-modal .ay-textarea { min-height: 54px; }
.ay-modal .ay-btn--lg { padding: 12px 26px; font-size: var(--ay-fs-sm); }
.ay-modal .ay-form__note { margin-top: 6px; font-size: 11.5px; }

/* On short viewports the branded panel sheds its secondary content so it never
   becomes the element forcing the dialog taller than the screen. */
@media (max-height: 700px) {
  .ay-modal__aside-logo,
  .ay-modal__points { display: none; }
  /* With the logo and trust list gone there is nothing to anchor to the top,
     so the remaining copy is centred rather than left floating at the bottom. */
  .ay-modal__aside-inner { padding: var(--ay-5); gap: var(--ay-4); justify-content: center; }
  .ay-modal__aside-body { margin-top: 0; }
  .ay-modal__main { padding: 54px var(--ay-5) var(--ay-5); }
  .ay-modal .ay-textarea { min-height: 48px; }
}

/* --- Responsive --------------------------------------------------------- */
/* Below 860px the split stops paying for itself: the branded panel becomes a
   short banner above the form and the trust list is dropped so the dialog
   still fits a phone screen. */
@media (max-width: 859px) {
  .ay-modal__grid { grid-template-columns: minmax(0, 1fr); }
  .ay-modal__aside-inner {
    padding: var(--ay-5);
    gap: var(--ay-3);
    flex-direction: row;
    align-items: center;
  }
  .ay-modal__aside-logo { display: none; }
  .ay-modal__aside-body { margin-top: 0; }
  .ay-modal__aside h3 { font-size: var(--ay-fs-lg); margin-bottom: 0; }
  .ay-modal__aside p,
  .ay-modal__points,
  .ay-modal__aside-wa { display: none; }
  .ay-modal__main { padding: var(--ay-5) var(--ay-4) var(--ay-4); }
  .ay-modal__main-head { display: none; }
  .ay-modal__close { top: var(--ay-3); right: var(--ay-3); background: rgba(255, 255, 255, .16); color: #fff; }
}

@media (max-width: 575px) {
  .ay-modal__aside-inner { padding: var(--ay-4); }
  .ay-modal__aside .ay-eyebrow { display: none; }
}

/* ==========================================================================
   Home
   ========================================================================== */
.ay-home .ay-solutions { position: relative; }

/* Coverage / reach band */
.ay-reach {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
@media (max-width: 991px) { .ay-reach { grid-template-columns: minmax(0, 1fr); } }

.ay-reach__points {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ay-4);
}
.ay-reach__point {
  padding: var(--ay-5);
  border: 1px solid var(--ay-border-invert);
  border-radius: var(--ay-r);
  background: rgba(255, 255, 255, .04);
}
.ay-reach__point i { color: var(--ay-red); font-size: 1.5rem; display: block; margin-bottom: var(--ay-2); }
.ay-reach__point strong { display: block; color: #fff; margin-bottom: 2px; }
.ay-reach__point span { font-size: var(--ay-fs-sm); color: var(--ay-text-on-invert-muted); }
@media (max-width: 479px) { .ay-reach__points { grid-template-columns: minmax(0, 1fr); } }

/* Testimonials: CSS grid on desktop, Swiper below 992px.
   The wrapper is targeted with a two-class selector so it beats Swiper's own
   `.swiper-wrapper { display: flex }` regardless of stylesheet order. */
.ay-quotes__dots { display: none; }

@media (min-width: 992px) {
  .ay-quotes__grid .swiper-wrapper {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--ay-5);
    transform: none !important;   /* Swiper is destroyed here, but be explicit */
  }
  .ay-quotes__grid .swiper-slide { width: auto; height: auto; }
}

@media (max-width: 991px) {
  .ay-quotes__dots {
    display: flex;
    justify-content: center;
    gap: var(--ay-2);
    margin-top: var(--ay-5);
  }
  .ay-quotes__dots .swiper-pagination-bullet {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--ay-border);
    opacity: 1;
    cursor: pointer;
  }
  .ay-quotes__dots .swiper-pagination-bullet-active { background: var(--ay-red); width: 24px; border-radius: var(--ay-r-pill); }
  .ay-quotes__grid .swiper-slide { height: auto; }
  .ay-quotes__grid .ay-quote { height: 100%; }
}

/* ==========================================================================
   Products listing
   ========================================================================== */
.ay-products__layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: clamp(24px, 3vw, 48px);
  align-items: start;
}
@media (max-width: 991px) {
  .ay-products__layout { grid-template-columns: minmax(0, 1fr); }
}

.ay-sidebar {
  position: sticky;
  top: calc(var(--ay-header-h) + var(--ay-4));
  display: grid;
  gap: var(--ay-5);
}
@media (max-width: 991px) { .ay-sidebar { position: static; } }

.ay-sidebar__panel { display: grid; gap: var(--ay-5); }

.ay-sidebar__toggle {
  display: none;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r);
  padding: var(--ay-4) var(--ay-5);
  font-family: var(--ay-font);
  font-weight: var(--ay-fw-semi);
  font-size: var(--ay-fs-sm);
  color: var(--ay-text);
}
.ay-sidebar__toggle i { transition: transform var(--ay-dur-2) var(--ay-ease); }
.ay-sidebar__toggle[aria-expanded="true"] i { transform: rotate(180deg); }

@media (max-width: 991px) {
  /* Collapsed by default so the product grid a visitor came for is the
     first thing on screen; the full tree is one tap away behind the
     toggle, not a scroll away. */
  .ay-sidebar__toggle { display: flex; }
  .ay-sidebar__panel { display: none; }
  .ay-sidebar__panel.is-open { display: grid; }
}

.ay-sidebar__block {
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r);
  padding: var(--ay-5);
}
.ay-sidebar__title {
  font-family: var(--ay-font);
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-bold);
  letter-spacing: var(--ay-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ay-text);
  padding-bottom: var(--ay-3);
  margin-bottom: var(--ay-3);
  border-bottom: 1px solid var(--ay-border);
}
.ay-sidebar__group + .ay-sidebar__group { margin-top: var(--ay-4); }
/* Category: black by default, so the list reads as one plain menu; the
   category matching the page actually being viewed is the theme red, so it
   can be found by colour at a glance. :link/:visited are stated explicitly
   on both -- without them the browser's own visited-link colour (which a
   category you're currently on always qualifies as, having just been
   navigated to) would beat the plain class rule and read as "not active"
   the moment it turned out to be the one you're on. */
.ay-sidebar__cat {
  display: block;
  font-weight: var(--ay-fw-bold);
  font-size: var(--ay-fs-sm);
  margin-bottom: var(--ay-1);
}
.ay-sidebar__cat:link,
.ay-sidebar__cat:visited { color: var(--ay-ink); }
.ay-sidebar__cat:hover { color: var(--ay-accent-text); }
.ay-sidebar__cat.is-active:link,
.ay-sidebar__cat.is-active:visited { color: var(--ay-accent-text); }

/* Sub-category: a lighter black, normal weight -- plainly a child link, not
   another heading. The active one currently being viewed stays the same
   colour but goes bold, so it's found by weight rather than by switching to
   the category's red (which would read as if it were a second heading). */
.ay-sidebar__sub a {
  display: block;
  padding: 6px 0 6px var(--ay-3);
  font-size: var(--ay-fs-sm);
  font-weight: var(--ay-fw-normal);
  border-left: 2px solid var(--ay-border);
}
.ay-sidebar__sub a:link,
.ay-sidebar__sub a:visited { color: var(--ay-ink-700); }
.ay-sidebar__sub a:hover { color: var(--ay-accent-text); border-left-color: var(--ay-red); }
.ay-sidebar__sub a.is-active {
  font-weight: var(--ay-fw-bold);
  border-left-color: var(--ay-red);
}

.ay-sidebar__cta {
  background: var(--ay-ink);
  color: var(--ay-text-on-invert);
  border-radius: var(--ay-r);
  padding: var(--ay-5);
  text-align: center;
}
.ay-sidebar__cta h4 { color: #fff; font-size: var(--ay-fs-lg); margin-bottom: var(--ay-2); }
.ay-sidebar__cta p { font-size: var(--ay-fs-sm); color: var(--ay-text-on-invert-muted); margin-bottom: var(--ay-4); }

.ay-results-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ay-4);
  flex-wrap: wrap;
  margin-bottom: var(--ay-5);
}
.ay-results-head p { color: var(--ay-text-muted); font-size: var(--ay-fs-sm); }

/* ==========================================================================
   Product detail
   ========================================================================== */
.ay-detail {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(28px, 4vw, 60px);
  align-items: start;
}
@media (max-width: 991px) { .ay-detail { grid-template-columns: minmax(0, 1fr); } }

/* The frame is capped on its own rather than relying on the grid column to
   size it. In the two-column layout the column is already narrower than
   this, so the cap does nothing; but the frame carries `aspect-ratio: 4/3`,
   so ANY state where it ends up full width -- the stacked layout, a
   stylesheet that has not applied yet, a browser holding an older copy --
   produced a frame over a thousand pixels tall with a small photo
   marooned in the middle of it. Capping it here means that cannot happen
   whatever the column does. */
.ay-gallery__main {
  /* Matches the listing card's media background so the padding around the
     photo is imperceptible against the page, rather than reading as a grey
     frame the photo stops short of. */
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  /* Rounded on top only, like the listing card's image sits above its
     square-cornered body -- not a standalone rounded tile. */
  border-radius: var(--ay-r-lg) var(--ay-r-lg) 0 0;
  overflow: hidden;
  position: relative;
  max-width: 620px;
  margin-inline: auto;
}
.ay-gallery__main .swiper-slide {
  position: relative;
  /* Taller than the old 4:3, and `contain` below rather than `cover` --
     most uploads are a camera or panel shot taller than it is wide, and
     4:3 + cover cropped in on it, cutting the top off the product itself
     rather than just trimming backdrop. This is the one shot a buyer is
     actually deciding on, so nothing about it should be cropped away. */
  aspect-ratio: 4 / 5;
  /* Swiper's own wrapper/slide elements carry no radius of their own, so
     without this the square slide showed through the rounded corners of
     the frame around it. */
  border-radius: inherit;
  overflow: hidden;
}
.ay-gallery__main img {
  position: absolute;
  inset: var(--ay-4);
  width: calc(100% - var(--ay-4) * 2);
  height: calc(100% - var(--ay-4) * 2);
  object-fit: contain;
  object-position: center;
}
.ay-gallery__thumbs { margin-top: var(--ay-3); max-width: 620px; margin-inline: auto; }
.ay-gallery__thumbs .swiper-slide {
  position: relative;
  aspect-ratio: 1;
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r-sm);
  overflow: hidden;
  cursor: pointer;
  opacity: .55;
  transition: opacity var(--ay-dur-1) var(--ay-ease), border-color var(--ay-dur-1) var(--ay-ease);
}
.ay-gallery__thumbs .swiper-slide-thumb-active { opacity: 1; border-color: var(--ay-red); }
.ay-gallery__thumbs img {
  position: absolute;
  inset: var(--ay-2);
  width: calc(100% - var(--ay-2) * 2);
  height: calc(100% - var(--ay-2) * 2);
  object-fit: scale-down;
  object-position: center;
}

.ay-detail__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ay-2) var(--ay-4);
  margin-bottom: var(--ay-4);
}
.ay-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ay-1);
  padding: 6px 14px;
  border-radius: var(--ay-r-pill);
  background: var(--ay-red-50);
  color: var(--ay-red-600);
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-semi);
}
.ay-chip--muted { background: var(--ay-surface-2); color: var(--ay-text-muted); }

.ay-detail__desc { color: var(--ay-text-muted); margin-block: var(--ay-4); }
.ay-detail__desc :where(p) { margin-bottom: var(--ay-3); }
/* Headings carry the editor's own hierarchy (h1-h3, per the CKEditor
   format_tags config) -- set apart from the muted body copy, not inheriting
   its colour, or "Heading" and "paragraph" render identically. */
.ay-detail__desc :where(h1, h2, h3, h4) {
  color: var(--ay-ink);
  font-weight: var(--ay-fw-bold);
  line-height: var(--ay-lh-snug);
  margin: var(--ay-5) 0 var(--ay-3);
}
.ay-detail__desc :where(h1, h2) { font-size: var(--ay-fs-xl); }
.ay-detail__desc :where(h3, h4) { font-size: var(--ay-fs-lg); }
.ay-detail__desc :where(h1, h2, h3, h4):first-child { margin-top: 0; }
.ay-detail__desc :where(strong, b) { color: var(--ay-ink); font-weight: var(--ay-fw-bold); }
.ay-detail__desc :where(a) { color: var(--ay-accent-text); text-decoration: underline; }
.ay-detail__desc :where(ul, ol) { padding-left: var(--ay-5); margin-bottom: var(--ay-3); }
.ay-detail__desc :where(ul) { list-style: disc; }
.ay-detail__desc :where(ol) { list-style: decimal; }
.ay-detail__desc :where(li) { margin-bottom: var(--ay-1); }
.ay-detail__desc :where(blockquote) {
  margin: var(--ay-4) 0;
  padding-left: var(--ay-4);
  border-left: 3px solid var(--ay-border);
  color: var(--ay-ink);
  font-style: italic;
}
/* A resize in the editor is saved as an inline width/height on the img
   itself -- max-width still caps that on a viewport narrower than the
   chosen size, and height:auto keeps it proportional rather than
   squashed once width gives way. */
.ay-detail__desc :where(img) {
  max-width: 100%;
  height: auto;
  border-radius: var(--ay-r-sm);
  margin-block: var(--ay-3);
}
.ay-detail__desc :where(table) { width: 100%; font-size: var(--ay-fs-sm); }
.ay-detail__desc :where(td, th) { border: 1px solid var(--ay-border); padding: var(--ay-2) var(--ay-3); }

/* The description editor (Quill) marks font, size, alignment and indent
   with classes rather than inline styles -- colour and background are
   inline already and need nothing here. Values match Quill's own
   defaults so a pick in the editor looks the same on the live page. */
.ay-detail__desc .ql-font-serif { font-family: Georgia, 'Times New Roman', serif; }
.ay-detail__desc .ql-font-monospace { font-family: Monaco, 'Courier New', monospace; }
.ay-detail__desc .ql-size-small { font-size: .75em; }
.ay-detail__desc .ql-size-large { font-size: 1.5em; }
.ay-detail__desc .ql-size-huge { font-size: 2.5em; }
.ay-detail__desc .ql-align-center { text-align: center; }
.ay-detail__desc .ql-align-right { text-align: right; }
.ay-detail__desc .ql-align-justify { text-align: justify; }
.ay-detail__desc .ql-direction-rtl { direction: rtl; text-align: inherit; }
.ay-detail__desc .ql-indent-1 { padding-left: 3em; }
.ay-detail__desc .ql-indent-2 { padding-left: 6em; }
.ay-detail__desc .ql-indent-3 { padding-left: 9em; }
.ay-detail__desc .ql-indent-4 { padding-left: 12em; }
.ay-detail__desc .ql-indent-5 { padding-left: 15em; }
.ay-detail__desc .ql-indent-6 { padding-left: 18em; }
.ay-detail__desc .ql-indent-7 { padding-left: 21em; }
.ay-detail__desc .ql-indent-8 { padding-left: 24em; }

/* The summary column runs far longer than the image beside it, mostly because
   the quote form lives in it. Left alone the gallery scrolls away and the
   product is off-screen while somebody fills the form in about it. Sticky
   only where there are two columns; below that they are stacked and there is
   nothing to stick to. */
@media (min-width: 992px) {
  .ay-detail > :first-child {
    position: sticky;
    top: calc(var(--ay-header-h) + var(--ay-4));
    align-self: start;
  }
}

/* --------------------------------------------------------------------------
   Product detail — the summary column

   Ordered the way a buyer reads it: who makes it, what it is, what it costs,
   what it does, then how to ask. WhatsApp is the primary action rather than
   one of three equals -- it is the channel this business closes on, and it
   opens with the product already named.
   -------------------------------------------------------------------------- */

/* The trail back into the catalogue -- category, then sub category, sat
   above the title rather than restated as chips below it. */
.ay-detail__crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--ay-2);
  margin: 0 0 var(--ay-3);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
}
.ay-detail__crumbs a {
  color: var(--ay-text-muted);
  text-decoration: none;
}
.ay-detail__crumbs a:hover { color: var(--ay-red); text-decoration: underline; }

.ay-detail__title {
  font-size: clamp(1.6rem, 3.2vw, 2.25rem);
  line-height: var(--ay-lh-tight);
  margin: 0 0 var(--ay-3);
}

/* Follows the model number on the same meta line -- both are product
   identity, sized to sit level with the chip beside it rather than as a
   larger mark of its own. */
.ay-detail__brand {
  display: flex;
  align-items: center;
  gap: var(--ay-2);
  flex: none;
}
.ay-detail__brand img {
  /* Height-bound with the width following: these logos run from square to
     16:9, and a fixed box renders the square ones unreadably small. */
  height: 20px;
  width: auto;
  max-width: 90px;
  object-fit: contain;
}
.ay-detail__brand span {
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-bold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ay-text-muted);
}

.ay-detail__meta { margin-bottom: var(--ay-4); }

/* The price, in the same parts as the listing card so the figure a visitor
   saw on the way in is the figure they see here. Sits above the description,
   right after the title and its chips -- the figure and the brand backing
   it up are what a buyer is qualifying first. Plainly set with a rule above
   rather than boxed in a tinted panel, so it reads as information rather
   than a checkout total. */
.ay-detail__price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--ay-3);
  margin: 0 0 var(--ay-5);
  padding-top: var(--ay-4);
  border-top: 1px solid var(--ay-border);
}
.ay-detail__price strong {
  font-family: var(--ay-font-display);
  font-size: var(--ay-fs-2xl);
  font-weight: var(--ay-fw-bold);
  color: var(--ay-ink);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
/* Set smaller than the figure and sat on its baseline -- ₹18,000 reads as
   one price, not a currency code stapled to a number. */
.ay-detail__currency {
  font-size: .55em;
  font-weight: var(--ay-fw-semi);
  margin-right: 2px;
}
.ay-detail__price s {
  font-size: var(--ay-fs-sm);
  font-weight: var(--ay-fw-normal);
  color: var(--ay-text-muted);
  text-decoration-thickness: 1px;
  font-variant-numeric: tabular-nums;
}
/* The saving, in its own colour so it reads as good news rather than
   another number in the line -- distinct from both the brand red (reserved
   for calls to action) and the WhatsApp green. */
.ay-detail__discount {
  padding: 4px 12px;
  border-radius: var(--ay-r-pill);
  background: var(--ay-success-50);
  color: var(--ay-success);
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-bold);
  letter-spacing: .01em;
}
.ay-detail__unit {
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
}
/* A statement about the sales process rather than a number, so it is not set
   in the price face. */
.ay-detail__price.is-onrequest {
  font-size: var(--ay-fs-lg);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-text-muted);
}

.ay-detail__lead {
  color: var(--ay-text-muted);
  font-size: var(--ay-fs-base);
  line-height: var(--ay-lh);
  margin: 0 0 var(--ay-5);
}

/* ------------------------------------------------------------ the CTA block */
.ay-detail__cta { margin-bottom: var(--ay-5); }

.ay-detail__cta-note {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin: var(--ay-2) 0 0;
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  line-height: 1.5;
}
.ay-detail__cta-note .las { color: var(--ay-wa); font-size: 1.1em; flex: none; margin-top: 1px; }

/* The two alternatives share a row and equal width: neither is preferred over
   the other, and both sit clearly below the WhatsApp button. */
.ay-detail__cta-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ay-2);
  margin-top: var(--ay-3);
}
.ay-detail__cta-row .ay-btn { width: 100%; padding-inline: var(--ay-4); }
/* --- Hover: a pop, and nothing else ----------------------------------------
   All three keep their exact colours under the cursor and answer with a
   small scale instead. Each modifier's colour hover has to be undone by
   name below, because restating the resting value is the only way to beat
   it -- there is no CSS for "ignore that rule".

   1.03, not the 1.045 the WhatsApp button used alone: these sit in a row,
   and a scale large enough to notice on a single button reads as the row
   jostling when it is applied to all of them.

   :focus-visible is deliberately untouched. It is the only thing telling a
   keyboard user where they are, and it is not a hover effect. */
.ay-detail__cta .ay-btn:hover  { transform: scale(1.03); }
.ay-detail__cta .ay-btn:active { transform: scale(.99); }

/* The scale is decoration; a reduced-motion preference gets the buttons
   still, which they remain perfectly usable as. */
@media (prefers-reduced-motion: reduce) {
  .ay-detail__cta .ay-btn:hover,
  .ay-detail__cta .ay-btn:active { transform: none; }
}
.ay-detail__cta .ay-btn--wa:hover    { --_bg: var(--ay-wa); --_fg: #fff; }
.ay-detail__cta .ay-btn--dark:hover  { --_bg: var(--ay-ink); --_fg: #fff; }
.ay-detail__cta .ay-btn--ghost:hover {
  --_bg: transparent;
  --_fg: var(--ay-text);
  --_bd: var(--ay-border);
}
@media (max-width: 400px) {
  .ay-detail__cta-row { grid-template-columns: minmax(0, 1fr); }
}

/* What the price actually buys. On a system that is installed rather than
   shipped, this is the part a buyer is uncertain about. */
.ay-detail__assure {
  list-style: none;
  margin: 0 0 var(--ay-5);
  padding: var(--ay-4);
  background: var(--ay-surface-2);
  border-radius: var(--ay-r);
  display: grid;
  gap: var(--ay-2);
}
.ay-detail__assure li {
  display: flex;
  align-items: center;
  gap: var(--ay-2);
  font-size: var(--ay-fs-sm);
  color: var(--ay-text);
}
.ay-detail__assure .las { color: var(--ay-red); font-size: 1.15em; flex: none; }

/* Inline enquiry panel — the highest-intent form on the site, so it is on the
   page rather than hidden behind a modal. */
.ay-detail__enquiry {
  margin-top: var(--ay-6);
  background: var(--ay-surface);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r-lg);
  padding: clamp(20px, 3vw, 32px);
}
.ay-detail__enquiry h3 { font-size: var(--ay-fs-xl); margin-bottom: var(--ay-2); }
.ay-detail__enquiry > p { color: var(--ay-text-muted); font-size: var(--ay-fs-sm); margin-bottom: var(--ay-5); }

/* ==========================================================================
   About
   ========================================================================== */
.ay-timeline { display: grid; gap: var(--ay-5); }
.ay-timeline__item {
  position: relative;
  padding-left: var(--ay-7);
}
.ay-timeline__item::before {
  content: "";
  position: absolute;
  left: 11px; top: 26px; bottom: -24px;
  width: 2px;
  background: var(--ay-border);
}
.ay-timeline__item:last-child::before { display: none; }
.ay-timeline__dot {
  position: absolute;
  left: 0; top: 4px;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--ay-red-50);
  border: 2px solid var(--ay-red);
  display: grid;
  place-items: center;
}
.ay-timeline__dot::after {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--ay-red);
}
.ay-timeline__year {
  font-family: var(--ay-font-display);
  font-size: var(--ay-fs-xl);
  font-weight: var(--ay-fw-bold);
  color: var(--ay-accent-text);
}
.ay-timeline__item p { color: var(--ay-text-muted); font-size: var(--ay-fs-sm); margin-top: var(--ay-1); }

/* ==========================================================================
   Contact
   ========================================================================== */
.ay-contact__layout {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
@media (max-width: 991px) { .ay-contact__layout { grid-template-columns: minmax(0, 1fr); } }

.ay-contact__cards { display: grid; gap: var(--ay-4); }
.ay-contact__card {
  display: flex;
  gap: var(--ay-4);
  padding: var(--ay-5);
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r);
  transition: border-color var(--ay-dur-2) var(--ay-ease), box-shadow var(--ay-dur-2) var(--ay-ease);
}
.ay-contact__card:hover { border-color: transparent; box-shadow: var(--ay-shadow-2); }
.ay-contact__icon {
  flex: none;
  width: 50px; height: 50px;
  display: grid; place-items: center;
  border-radius: var(--ay-r-sm);
  background: var(--ay-red-50);
  color: var(--ay-red);
  font-size: 1.4rem;
}
.ay-contact__card h4 { font-size: var(--ay-fs-base); font-family: var(--ay-font); margin-bottom: 2px; }
.ay-contact__card p,
.ay-contact__card a { color: var(--ay-text-muted); font-size: var(--ay-fs-sm); }
.ay-contact__card a:hover { color: var(--ay-accent-text); }


/* ==========================================================================
   Success dialog

   Shown after an enquiry is accepted. A dialog rather than a bar: the
   confirmation is the one moment worth interrupting for, and a bar above the
   fold is easy to miss on a long page.
   ========================================================================== */
.ay-done .ay-done__content {
  position: relative;
  border: 0;
  border-radius: var(--ay-r-lg);
  box-shadow: var(--ay-shadow-3);
  overflow: hidden;
  text-align: center;
}
.ay-done .modal-dialog { max-width: 440px; }

.ay-done__body { padding: clamp(32px, 5vw, 48px) clamp(24px, 4vw, 40px); }

.ay-done__title {
  margin: var(--ay-4) 0 0;
  font-size: var(--ay-fs-2xl);
  line-height: 1.15;
  color: var(--ay-ink);
}
.ay-done__msg {
  margin: var(--ay-3) 0 0;
  font-size: var(--ay-fs-sm);
  color: var(--ay-text-muted);
  line-height: 1.6;
}

.ay-done__actions {
  margin-top: var(--ay-5);
  display: flex;
  flex-direction: column;
  gap: var(--ay-2);
}
.ay-done__actions .ay-btn { width: 100%; justify-content: center; }

/* --- The tick ------------------------------------------------------------
   Two strokes drawn in sequence: the ring, then the check. Both are dashed to
   their own length and animated from fully offset to zero, which is what makes
   them appear to be drawn rather than to fade in.
   ------------------------------------------------------------------------- */
.ay-done__tick {
  width: 84px;
  height: 84px;
  display: block;
  margin: 0 auto;
}
.ay-done__tick-ring,
.ay-done__tick-mark {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ay-done__tick-ring {
  stroke: var(--ay-accent);
  stroke-width: 2.5;
  /* 2πr for r=24, rounded up so the dash never falls a hair short. */
  stroke-dasharray: 152;
  stroke-dashoffset: 152;
  animation: ay-tick-ring 620ms var(--ay-ease-out) forwards;
}
.ay-done__tick-mark {
  stroke: var(--ay-accent);
  stroke-width: 3.5;
  stroke-dasharray: 40;
  stroke-dashoffset: 40;
  /* Starts as the ring finishes, so it reads as one gesture. */
  animation: ay-tick-mark 320ms var(--ay-ease-out) 480ms forwards;
}

@keyframes ay-tick-ring { to { stroke-dashoffset: 0; } }
@keyframes ay-tick-mark { to { stroke-dashoffset: 0; } }

/* A soft pulse behind the tick, once, as the check lands. */
.ay-done__tick { position: relative; }
.ay-done__body::before {
  content: "";
  display: block;
  width: 84px;
  height: 84px;
  margin: 0 auto -84px;
  border-radius: 50%;
  background: var(--ay-red-50);
  transform: scale(0);
  animation: ay-tick-pulse 520ms var(--ay-ease-out) 440ms forwards;
}
@keyframes ay-tick-pulse {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Reduced motion: the tick is already drawn, and nothing moves. */
@media (prefers-reduced-motion: reduce) {
  .ay-done__tick-ring,
  .ay-done__tick-mark { animation: none; stroke-dashoffset: 0; }
  .ay-done__body::before { animation: none; transform: scale(1); opacity: 1; }
}

/* ==========================================================================
   Brand facet — the filter row above a product listing
   ========================================================================== */
.ay-facet {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ay-2);
  margin-bottom: var(--ay-5);
  padding-bottom: var(--ay-4);
  border-bottom: 1px solid var(--ay-line);
}
.ay-facet__label {
  font-size: var(--ay-fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--ay-tracking-eyebrow);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-text-muted);
  margin-right: var(--ay-1);
}
.ay-facet__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r-pill);
  background: var(--ay-white);
  font-size: var(--ay-fs-sm);
  color: var(--ay-text);
  line-height: 1.3;
  transition: border-color var(--ay-dur-2) var(--ay-ease), color var(--ay-dur-2) var(--ay-ease),
              background-color var(--ay-dur-2) var(--ay-ease);
}
.ay-facet__chip:hover { border-color: var(--ay-ink); color: var(--ay-ink); text-decoration: none; }
.ay-facet__chip b {
  font-weight: var(--ay-fw-semi);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  font-variant-numeric: tabular-nums;
}
.ay-facet__chip.is-on {
  background: var(--ay-ink);
  border-color: var(--ay-ink);
  color: var(--ay-text-on-invert);
}
.ay-facet__chip.is-on b { color: var(--ay-text-on-invert-muted); }
.ay-facet__chip:focus-visible { box-shadow: var(--ay-focus); outline: none; }

/* Below the sidebar breakpoint the row scrolls sideways in its own strip
   rather than stacking into four lines of chips above the results. */
@media (max-width: 575px) {
  .ay-facet {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .ay-facet::-webkit-scrollbar { display: none; }
  .ay-facet__chip, .ay-facet__label { flex: none; }
}



/* ==========================================================================
   Our clients

   A wall of logos owned by other organisations: nine files ranging from 182px
   square to a 900x500 landscape to a 1700x2000 portrait. The old page forced
   `height: 180px` on the <img> with no object-fit, which stretched every one
   of them out of shape. Here each logo sits untouched inside a fixed frame and
   the frame does the aligning.
   ========================================================================== */
.ay-clientgrid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* auto-fill with a floor rather than fixed column counts: the grid reflows
     from four across to one without a media query per step. */
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--ay-4);
}

.ay-client {
  display: flex;
  flex-direction: column;
  background: var(--ay-white);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r);
  overflow: hidden;
  /* No hover state, and no transition to drive one. These cards are not
     links -- there is nowhere to go from a client logo -- so lifting one
     under the cursor promised an interaction the card cannot deliver. */
}

/* The frame. A fixed ratio gives every logo the same visual weight however
   differently shaped the file is, which is what makes a mixed set read as a
   deliberate wall rather than a pile. */
.ay-client__mark {
  position: relative;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: var(--ay-4);
  background: var(--ay-white);
}
/* Absolutely positioned inside the frame, the same way the product media and
   the detail gallery do it. `aspect-ratio` sets a preferred height but yields
   to content that overflows: the 1700x2000 portrait logo pushed its own frame
   taller than 3:2 and knocked that card's name band out of line with the rest
   of the row. Taking the image out of flow means nothing can stretch the
   frame, so every card in a row matches.

   `scale-down`, not `contain`: contain would blow a 182px logo up to fill the
   frame and render it soft. This never draws one past its own pixels, so a
   small file simply sits smaller — honest, and better than a blurred one. */
.ay-client__mark img {
  position: absolute;
  inset: var(--ay-4);
  width: calc(100% - var(--ay-4) * 2);
  height: calc(100% - var(--ay-4) * 2);
  object-fit: scale-down;
  object-position: center;
}

.ay-client__initials {
  font-family: var(--ay-font-display);
  font-size: var(--ay-fs-2xl);
  font-weight: var(--ay-fw-bold);
  color: var(--ay-slate-400);
  letter-spacing: .02em;
}

/* The name sits on its own band, separated by a rule rather than a colour
   change, so the eye reads logo and name as one card. */
.ay-client__name {
  margin: auto 0 0;
  padding: var(--ay-3) var(--ay-4);
  border-top: 1px solid var(--ay-line);
  background: var(--ay-surface-2);
  font-size: var(--ay-fs-sm);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-ink);
  text-align: center;
  line-height: var(--ay-lh-snug);
}

@media (max-width: 575px) {
  /* Two across on a phone rather than one: these are recognised at a glance,
     and a single column turns nine logos into a long scroll. */
  .ay-clientgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ay-3); }
  .ay-client__mark { padding: var(--ay-3); }
  .ay-client__mark img {
    inset: var(--ay-3);
    width: calc(100% - var(--ay-3) * 2);
    height: calc(100% - var(--ay-3) * 2);
  }
  .ay-client__name { padding: var(--ay-2) var(--ay-3); font-size: var(--ay-fs-xs); }
}

/* ==========================================================================
   Blog listing

   Posts on the left, popular and categories on the right. No author anywhere:
   every post is by the same firm, so a byline repeated down the page carries
   no information.
   ========================================================================== */
.ay-blog__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
@media (max-width: 991px) {
  /* Sidebar under the posts: on a phone the posts are what was come for. */
  .ay-blog__layout { grid-template-columns: minmax(0, 1fr); }
}

/* --- the post list ------------------------------------------------------- */
.ay-postlist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--ay-5);
}

/* A row, not a card grid: at this width a horizontal row gives the title and
   summary room to be read, which is what decides whether a post is opened. */
.ay-post {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: var(--ay-5);
  align-items: center;
  padding-bottom: var(--ay-5);
  border-bottom: 1px solid var(--ay-line);
}
.ay-postlist > .ay-post:last-child { padding-bottom: 0; border-bottom: 0; }

.ay-post__media {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--ay-r);
  overflow: hidden;
  background: var(--ay-surface-2);
  display: grid;
  place-items: center;
}
/* Absolutely positioned so a tall upload cannot stretch the frame, the same
   pattern as the product media. `cover` here rather than `contain`: these are
   photographs, and a photograph filling its frame is the point. */
.ay-post__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform var(--ay-dur-3) var(--ay-ease-out);
}
.ay-post:hover .ay-post__media img { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) {
  .ay-post:hover .ay-post__media img { transform: none; }
}
.ay-post__media .las { font-size: 2.4rem; color: var(--ay-slate-400); }

.ay-post__body { min-width: 0; }

.ay-post__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ay-2);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  margin-bottom: var(--ay-2);
}
.ay-post__cat {
  text-transform: uppercase;
  letter-spacing: var(--ay-tracking-eyebrow);
  font-weight: var(--ay-fw-bold);
  color: var(--ay-red);
}
/* A dot between the category and the date, drawn rather than typed so it is
   not read aloud by a screen reader. */
.ay-post__cat + time::before { content: "·"; margin-right: var(--ay-2); }

.ay-post__title {
  font-size: var(--ay-fs-xl);
  line-height: var(--ay-lh-snug);
  margin: 0 0 var(--ay-2);
}
.ay-post__title a { transition: color var(--ay-dur-1) var(--ay-ease); }
.ay-post:hover .ay-post__title a { color: var(--ay-red); }

.ay-post__excerpt {
  margin: 0 0 var(--ay-3);
  color: var(--ay-text-muted);
  font-size: var(--ay-fs-sm);
  line-height: 1.6;
  /* Three lines, then the browser places the ellipsis at the true end of the
     line — a character count cannot, because the column width varies. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ay-post__foot { display: flex; justify-content: flex-start; }

/* .ay-btn styling makes this read as a call to action; it stays a <span>
   (see the note in Blog.blade.php) rather than becoming a real link. */
.ay-post__more .las { transition: transform var(--ay-dur-1) var(--ay-ease); }
.ay-post:hover .ay-post__more .las { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .ay-post:hover .ay-post__more .las { transform: none; }
}

.ay-postlist__foot { margin-top: var(--ay-6); }

@media (max-width: 575px) {
  /* Stacked: a 260px image beside text leaves neither enough room. */
  .ay-post { grid-template-columns: minmax(0, 1fr); gap: var(--ay-3); }
  .ay-post__media { aspect-ratio: 16 / 9; }
  .ay-post__title { font-size: var(--ay-fs-lg); }
}

/* --- the sidebar --------------------------------------------------------- */
.ay-blogside { display: grid; gap: var(--ay-4); position: sticky; top: calc(var(--ay-header-h) + var(--ay-4)); }
@media (max-width: 991px) { .ay-blogside { position: static; } }

.ay-blogside__block {
  background: var(--ay-surface);
  border: 1px solid var(--ay-border);
  border-radius: var(--ay-r);
  padding: var(--ay-5);
}
.ay-blogside__block--cta { background: var(--ay-surface-2); }
.ay-blogside__block--cta p {
  margin: 0 0 var(--ay-4);
  font-size: var(--ay-fs-sm);
  color: var(--ay-text-muted);
  line-height: 1.6;
}

.ay-blogside__title {
  font-size: var(--ay-fs-base);
  margin: 0 0 var(--ay-4);
  padding-bottom: var(--ay-3);
  border-bottom: 1px solid var(--ay-line);
}

.ay-poplist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ay-3); }
.ay-pop { display: grid; grid-template-columns: 68px minmax(0, 1fr); gap: var(--ay-3); align-items: center; }
.ay-pop__media {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--ay-r-sm);
  overflow: hidden;
  background: var(--ay-surface-2);
  display: grid;
  place-items: center;
}
.ay-pop__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ay-pop__media .las { font-size: 1.2rem; color: var(--ay-slate-400); }
.ay-pop__text { min-width: 0; display: grid; gap: 2px; }
.ay-pop__title {
  font-size: var(--ay-fs-sm);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-ink);
  line-height: var(--ay-lh-snug);
  /* Two lines: a long headline should not push the row taller than its own
     thumbnail and break the rhythm of the list. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ay-pop:hover .ay-pop__title { color: var(--ay-red); }
.ay-pop__text time { font-size: var(--ay-fs-xs); color: var(--ay-text-muted); }

.ay-catlist { list-style: none; margin: 0; padding: 0; display: grid; }
.ay-catlist li + li { border-top: 1px solid var(--ay-line); }
.ay-catlist a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ay-3);
  padding: var(--ay-3) 0;
  font-size: var(--ay-fs-sm);
  color: var(--ay-text);
  transition: color var(--ay-dur-1) var(--ay-ease);
}
.ay-catlist a:hover { color: var(--ay-red); }
.ay-catlist a.is-active { color: var(--ay-red); font-weight: var(--ay-fw-semi); }
.ay-catlist a.is-active b { background: var(--ay-red-100); color: var(--ay-red-700); }
.ay-catlist b {
  font-size: var(--ay-fs-xs);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-text-muted);
  background: var(--ay-surface-2);
  border-radius: var(--ay-r-pill);
  padding: 2px 9px;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Article (blog detail)

   Shares .ay-blog__layout and the sidebar components with the blog listing,
   so the two pages stay in step by construction rather than by copying.
   ========================================================================== */
.ay-article__head { margin-bottom: var(--ay-5); }

.ay-article__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ay-2);
  font-size: var(--ay-fs-xs);
  color: var(--ay-text-muted);
  margin-bottom: var(--ay-3);
}
.ay-article__cat {
  text-transform: uppercase;
  letter-spacing: var(--ay-tracking-eyebrow);
  font-weight: var(--ay-fw-bold);
  color: var(--ay-red);
}
.ay-article__cat + time::before { content: "·"; margin-right: var(--ay-2); }

.ay-article__title {
  font-size: clamp(1.75rem, 3.4vw, 2.6rem);
  line-height: var(--ay-lh-tight);
  margin: 0 0 var(--ay-3);
}

/* The tagline, set as a standfirst: larger than the body and quieter than the
   headline, which is how a reader is told what the piece is about before
   committing to it. */
.ay-article__standfirst {
  margin: 0;
  font-size: var(--ay-fs-lg);
  line-height: 1.6;
  color: var(--ay-text-muted);
}

.ay-article__cover {
  margin: 0 0 var(--ay-6);
  border-radius: var(--ay-r-lg);
  overflow: hidden;
  background: var(--ay-surface-2);
}
/* Shown whole, never cropped — an article's own picture is chosen to be
   seen — but bounded. The uploads here are portrait posters (2407x3304),
   which at full column width render over 1000px tall and push the article
   itself off the screen. width:auto with both maxima set keeps the ratio
   without object-fit, and centres whatever shape arrives. */
.ay-article__cover img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 520px;
  margin-inline: auto;
}

/* --- the body -------------------------------------------------------------
   Admin-authored HTML out of CKEditor, which emits bare tags and no classes.
   Everything here is written against the elements themselves, so whatever the
   editor produces lands styled. `:where()` keeps specificity at zero so a
   future component inside the body can still override freely. */
.ay-prose {
  color: var(--ay-text);
  font-size: var(--ay-fs-base);
  line-height: 1.75;
}
.ay-prose :where(p) { margin: 0 0 var(--ay-4); }
.ay-prose :where(h2, h3, h4, h5) {
  color: var(--ay-ink);
  line-height: var(--ay-lh-snug);
  margin: var(--ay-6) 0 var(--ay-3);
}
.ay-prose :where(h2) { font-size: var(--ay-fs-xl); }
.ay-prose :where(h3) { font-size: var(--ay-fs-lg); }
.ay-prose :where(h4, h5) { font-size: var(--ay-fs-base); }
.ay-prose :where(ul, ol) { margin: 0 0 var(--ay-4); padding-left: var(--ay-5); }
.ay-prose :where(ul) { list-style: disc; }
.ay-prose :where(ol) { list-style: decimal; }
.ay-prose :where(li) { margin-bottom: var(--ay-2); }
.ay-prose :where(a) { color: var(--ay-red); text-decoration: underline; text-underline-offset: 2px; }
.ay-prose :where(a):hover { color: var(--ay-red-700); }
.ay-prose :where(strong, b) { font-weight: var(--ay-fw-semi); color: var(--ay-ink); }
.ay-prose :where(img) {
  max-width: 100%;
  height: auto;
  border-radius: var(--ay-r);
  margin: var(--ay-4) 0;
}
.ay-prose :where(blockquote) {
  margin: var(--ay-5) 0;
  padding: var(--ay-2) 0 var(--ay-2) var(--ay-5);
  border-left: 3px solid var(--ay-red);
  color: var(--ay-ink);
  font-size: var(--ay-fs-lg);
  line-height: 1.6;
}
.ay-prose :where(blockquote p:last-child) { margin-bottom: 0; }
/* Tables and pre are the two things pasted into an editor that reliably run
   wider than the column; each scrolls inside itself rather than widening the
   page. */
.ay-prose :where(table) {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--ay-fs-sm);
  margin: 0 0 var(--ay-4);
}
.ay-prose :where(td, th) {
  border: 1px solid var(--ay-border);
  padding: var(--ay-2) var(--ay-3);
  text-align: left;
}
.ay-prose :where(pre) {
  overflow-x: auto;
  background: var(--ay-surface-2);
  border-radius: var(--ay-r-sm);
  padding: var(--ay-4);
  margin: 0 0 var(--ay-4);
}
.ay-prose > :last-child { margin-bottom: 0; }

/* --- foot ----------------------------------------------------------------- */
.ay-article__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ay-3);
  margin-top: var(--ay-6);
  padding-top: var(--ay-5);
  border-top: 1px solid var(--ay-line);
  font-size: var(--ay-fs-sm);
  color: var(--ay-text-muted);
}
.ay-article__share { display: flex; gap: var(--ay-2); }
.ay-article__share a {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--ay-border);
  border-radius: 50%;
  color: var(--ay-text);
  font-size: 1.05rem;
  transition: background-color var(--ay-dur-1) var(--ay-ease),
              border-color var(--ay-dur-1) var(--ay-ease),
              color var(--ay-dur-1) var(--ay-ease);
}
.ay-article__share a:hover { background: var(--ay-ink); border-color: var(--ay-ink); color: #fff; }

.ay-article__back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: var(--ay-5);
  font-size: var(--ay-fs-sm);
  font-weight: var(--ay-fw-semi);
  color: var(--ay-ink);
}
.ay-article__back:hover { color: var(--ay-red); }
