/* ==========================================================================
   OPPOSITE LOCK — MERGED DESIGN SYSTEM  ("Direction C")
   Palette + light grounds  ....... Direction A (Brand Guidelines v2.0)
   Radii, softness, containers,
   icon language, motion  ......... Direction B
   Built as a WordPress / WooCommerce / Elementor reference build.
   ========================================================================== */

:root{
  /* ---- SOURCE (Brand Guidelines v2.0) ---- */
  --navy:#002D52;
  --red:#FF1F2A;
  --deep:#001D36;
  --mid:#0C4372;

  /* ---- SURFACES (light-led) ---- */
  --white:#FFFFFF;
  --bone:#F4F1EA;
  --bone2:#EFEBE1;
  --bone3:#E7E2D6;
  --pale:#EAEEF7;
  --pale2:#F5F7FC;

  /* ---- TYPE & INTERFACE ---- */
  --graphite:#2A2F3A;
  --granite:#4A4F5A;
  --dust:#8A8F99;
  --redhover:#D6111B;
  --fit:#0F7B3E;

  /* ---- LINES ---- */
  --hair:rgba(0,45,82,.13);
  --hair2:rgba(0,45,82,.07);
  --hairw:rgba(255,255,255,.14);

  /* ---- GEOMETRY (from Direction B) ---- */
  --r:18px;      /* cards, panels          */
  --r2:12px;     /* small tiles, thumbs    */
  --r3:999px;    /* pills, buttons, chips  */
  --rbig:26px;   /* hero + campaign boxes  */
  --ease:cubic-bezier(.16,1,.3,1);

  /* ---- ELEVATION ---- */
  --e1:0 2px 6px rgba(0,45,82,.06);
  --e2:0 18px 34px -20px rgba(0,45,82,.30);
  --e3:0 28px 50px -26px rgba(0,45,82,.40);

  /* NAMESPACED ON PURPOSE. Do not rename this back to --display.
     Elementor writes --display:flex onto every container it renders. On any
     Elementor-built page those containers wrap these widgets, so our headings
     inherited the value flex -- and font-family:flex is valid CSS. It is a
     request for a font called flex. No such font exists, so the browser used
     its own default, which is a serif, and every display heading on the
     homepage came out in Times italic while the body and mono faces, whose
     token names Elementor does not use, were untouched. That is why the fault
     looked like a font that would not load and was nothing of the kind.
     --body and --mono are left alone: neither collides with anything loaded
     on this site today, and both were checked against Elementor and
     WooCommerce when this was found. */
  --ol-display:'Archivo Black',Impact,sans-serif;
  --body:'Archivo','Helvetica Neue',Arial,sans-serif;
  --mono:'JetBrains Mono','SFMono-Regular',Consolas,monospace;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
/* ==========================================================================
   TYPOGRAPHY  (readability pass, 3 Sep)
   Three changes, in the order they mattered:

   1. Base 14 -> 16px, with 14px the floor for anything secondary.
   2. The mono micro-labels were the real offender: 8.5-10px at .16em tracking,
      carrying real content (part codes, spec lines, section labels) below any
      defensible floor. Now 11.5px at roughly half the tracking.
   3. The uppercase italic display face is restricted to page and section
      headings and to numerals. It was doing UI work on card titles, category
      names and product names — the labels most likely to run long, which is
      exactly where uppercase italic costs most: uppercase removes word-shape
      and italic removes it again. Those are now sentence-case sans at 800.

   The pass adds page height; section padding gives it back, because the same
   brief asks for products higher up the page.
   ========================================================================== */
body{font-family:var(--body);background:var(--white);color:var(--graphite);
  -webkit-font-smoothing:antialiased;font-size:16px;line-height:1.62}
img{max-width:100%}
a{color:inherit;text-decoration:none}
/* The hover half of the rule above, and it has to be stated.
   Hello Elementor reset.css carries  a:active,a:hover{color:#336}  at
   specificity 0-1-1, which outranks any single class. Every component here
   that renders as an <a> and whose hover rule does not name a colour was
   therefore turning indigo on hover -- all four button variants among them.
   Components that carry a colour of their own restate it in section 32. */
a:hover,a:active{color:inherit}
button,input,select{font-family:inherit;font-size:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
::selection{background:var(--navy);color:#fff}
/* Widened from 1260 to 1440 at the client's request (27 Aug): with five nav
   tabs, the All button, the search field and the quote pill on one row, 1260
   was squashing them. Every grid inherits the extra width, so the whole page
   breathes rather than just the header. Gutter goes 36 -> 40 to match. */
.ol-container{max-width:1440px;margin:0 auto;padding:0 40px}

/* ==========================================================================
   1. (the utility ticker lived here — removed 3 Sep, see ol.ol-js)
   The slide keyframe stays: the brand strip still uses it.
   ========================================================================== */
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ==========================================================================
   2. HEADER — light, blurred, pill nav, circular icons  (B's icon language)
   ========================================================================== */
.ol-hdr{position:sticky;top:0;z-index:60;background:rgba(255,255,255,.88);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border-bottom:1px solid var(--hair)}
.ol-hdr .ol-container{display:flex;align-items:center;gap:20px;height:80px}
.ol-logo{display:block;flex-shrink:0;line-height:0}
.ol-logo img{display:block;height:56px;width:auto}
.ol-nav{display:flex;gap:4px;margin-left:6px}
.ol-nav a{display:inline-flex;align-items:center;gap:6px;font-size:14px;font-weight:600;
  color:var(--granite);padding:9px 17px;border-radius:var(--r3);
  transition:.22s var(--ease);white-space:nowrap}
.ol-nav a:hover{background:var(--bone);color:var(--navy)}
.ol-nav a.ol-on{background:var(--navy);color:#fff}
/* Explore leaves the site, so it says so */
.ol-extico{opacity:.55;flex-shrink:0;transform:translateY(-1px)}
.ol-nav a:hover .ol-extico{opacity:.9}
.ol-tools{margin-left:auto;display:flex;align-items:center;gap:9px}
.ol-srch{display:flex;align-items:center;gap:9px;background:var(--white);
  border:1px solid var(--hair);border-radius:var(--r3);padding:0 18px;height:42px;
  width:230px;transition:.25s var(--ease);position:relative;flex-shrink:0}
.ol-srch:focus-within{width:320px;border-color:var(--navy);box-shadow:var(--e1)}
/* padding:0 is not redundant. Hello reset.css gives every text input
   padding:.5rem 1rem, and this rule never restated it, so the field lost
   32px of room and clipped the placeholder mid-word. */
.ol-srch input{border:0;outline:0;background:none;width:100%;font-size:14px;padding:0}
.ol-srch input::placeholder{color:var(--dust)}
.ol-srch .ol-mag{color:var(--dust);flex-shrink:0}
.ol-ico{width:40px;height:40px;display:grid;place-items:center;border-radius:50%;
  background:var(--white);border:1px solid var(--hair);color:var(--navy);
  position:relative;transition:.22s var(--ease);flex-shrink:0}
.ol-ico:hover{transform:translateY(-2px);box-shadow:0 8px 18px -8px rgba(0,45,82,.4);
  border-color:transparent}
.ol-ico .ol-badge{position:absolute;top:-3px;right:-3px;background:var(--red);color:#fff;
  font-family:var(--mono);font-size:11.5px;font-weight:700;min-width:18px;height:18px;
  padding:0 4px;border-radius:var(--r3);display:grid;place-items:center;line-height:1}

/* ---- "All" button + category sidebar (client, Aug 27) ----
   The button sits before the logo: it is the first thing you reach for, and on
   a phone it is the only navigation there is, so it earns the leftmost slot.
   The panel it opens was a full-width dropdown showing everything at once; it
   is now a left drawer with a search field on top and the eight systems
   collapsed below. Eight systems and fifty-odd children is a wall to read, and
   a wall is slower than a list even though it shows more.
   One component now serves every width, so there is no separate mobile menu. */
.ol-allbtn{display:flex;align-items:center;gap:8px;flex-shrink:0;height:40px;
  padding:0 16px 0 13px;border-radius:var(--r3);background:var(--navy);color:#fff;
  font-size:14px;font-weight:700;transition:.22s var(--ease);cursor:pointer}
.ol-allbtn:hover{background:var(--deep)}
.ol-allbtn[aria-expanded="true"]{background:var(--red)}
.ol-allbtn svg{flex-shrink:0}

.ol-quotebtn{flex-shrink:0;white-space:nowrap}

/* the drawer itself */
html.ol-side-locked,html.ol-side-locked body{overflow:hidden}
.ol-sidewrap{position:fixed;inset:0;z-index:200}
.ol-scrim{position:absolute;inset:0;background:rgba(0,20,38,.5);opacity:0;
  transition:opacity .34s var(--ease)}
.ol-sidewrap.ol-open .ol-scrim{opacity:1}
.ol-side{position:absolute;left:0;top:0;bottom:0;width:390px;max-width:90vw;
  background:#fff;display:flex;flex-direction:column;
  transform:translateX(-101%);transition:transform .34s var(--ease);
  box-shadow:0 0 70px rgba(0,29,54,.34)}
.ol-sidewrap.ol-open .ol-side{transform:none}

.ol-side-top{background:var(--navy);color:#fff;padding:18px 20px 20px;flex-shrink:0}
.ol-side-row{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:15px}
.ol-side-ttl{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:21px;
  text-transform:uppercase;letter-spacing:-.02em}
/* The cross is an SVG, not the multiplication character. A glyph is centred
   on the typographic maths axis rather than in its own line box, so grid
   centring put it visibly high in the circle. Geometry cannot drift. */
.ol-side-x{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  padding:0;background:rgba(255,255,255,.1);color:#fff;
  transition:.2s var(--ease)}
.ol-side-x:hover{background:var(--red)}
.ol-side-srch{display:flex;align-items:center;gap:10px;background:rgba(255,255,255,.1);
  border:1px solid rgba(255,255,255,.18);border-radius:var(--r3);
  padding:0 16px;height:44px;position:relative}
.ol-side-srch:focus-within{background:#fff}
.ol-side-srch .ol-mag{color:rgba(255,255,255,.6);flex-shrink:0}
.ol-side-srch:focus-within .ol-mag{color:var(--dust)}
.ol-side-srch input{border:0;outline:0;background:none;width:100%;font-size:14px;color:#fff;padding:0}
.ol-side-srch input::placeholder{color:rgba(255,255,255,.55)}
.ol-side-srch:focus-within input{color:var(--navy)}
/* the field inverts to white on focus, so the placeholder has to come with it */
.ol-side-srch:focus-within input::placeholder{color:var(--dust)}
.ol-side-srch .ol-sugg{top:52px;left:0;right:0}

.ol-side-body{flex:1;overflow-y:auto;overscroll-behavior:contain;padding-bottom:14px}
.ol-side-nav{display:none}
.ol-side-h{font-family:var(--mono);font-size:11.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dust);padding:20px 20px 9px}

/* one collapsed row per system */
.ol-sd{border-bottom:1px solid var(--hair2)}
.ol-sd summary{display:flex;align-items:center;gap:12px;padding:14px 20px;
  cursor:pointer;list-style:none;transition:background .16s}
.ol-sd summary::-webkit-details-marker{display:none}
.ol-sd summary:hover{background:var(--bone)}
.ol-sd-ic{width:30px;height:26px;flex-shrink:0;display:grid;place-items:center}
.ol-sd-ic svg{width:28px;height:24px;color:var(--mid);opacity:.55}
.ol-sd-n{font-weight:800;font-size:14px;color:var(--navy);flex:1;min-width:0}
.ol-sd summary em{font-family:var(--mono);font-style:normal;font-size:11.5px;
  letter-spacing:.1em;color:var(--dust);flex-shrink:0}
.ol-sd-chev{color:var(--dust);display:grid;place-items:center;flex-shrink:0;
  transform:rotate(90deg);transition:transform .26s var(--ease)}
.ol-sd[open] .ol-sd-chev{transform:rotate(-90deg);color:var(--red)}
.ol-sd[open] summary{background:var(--bone)}
.ol-sd[open] .ol-sd-ic svg{color:var(--navy);opacity:.8}
.ol-sd-body{padding:6px 20px 18px 62px;background:var(--bone)}
.ol-sd-all{display:flex;align-items:center;gap:7px;font-size:14px;font-weight:800;
  color:var(--red);padding:5px 0 9px}
.ol-sd-all span{transition:transform .22s var(--ease)}
.ol-sd-all:hover span{transform:translateX(4px)}
.ol-sd-sub{display:block;font-size:14px;color:var(--granite);padding:6px 0;
  transition:.16s var(--ease)}
.ol-sd-sub:hover{color:var(--navy);transform:translateX(3px)}
.ol-sd-br{margin-top:12px;padding-top:12px;border-top:1px solid var(--bone3)}
.ol-sd-br>span{display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dust);margin-bottom:8px}
.ol-sd-br a{display:inline-block;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em;text-transform:uppercase;color:var(--mid);
  border:1px solid var(--hair);background:#fff;border-radius:var(--r3);
  padding:4px 9px;margin:0 5px 5px 0;transition:.18s var(--ease)}
.ol-sd-br a:hover{background:var(--navy);border-color:var(--navy);color:#fff}

/* flat rows: vehicles, deals, the odds and ends */
.ol-sd-flat{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:11px 20px;font-size:14px;font-weight:600;color:var(--navy);
  border-bottom:1px solid var(--hair2);transition:.16s}
.ol-sd-flat:hover{background:var(--bone);color:var(--red)}
.ol-sd-flat em{font-family:var(--mono);font-style:normal;font-size:11.5px;color:var(--dust)}
.ol-sd-flat-l{color:var(--red);font-weight:800;border-bottom:0}

.ol-side-foot{flex-shrink:0;padding:16px 20px;border-top:1px solid var(--hair);
  background:#fff}

.ol-mflag{font-family:var(--mono);font-size:11.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;background:var(--fit);color:#fff;border-radius:var(--r3);
  padding:2px 6px;vertical-align:1px;margin-left:4px}
.ol-mflag-hot{background:var(--red)}

/* search suggestions */
.ol-sugg{position:absolute;top:46px;left:0;right:0;background:#fff;border:1px solid var(--hair);
  border-radius:var(--r);box-shadow:var(--e3);padding:8px;display:none;z-index:80;
  max-height:330px;overflow:auto}
.ol-sugg.ol-open{display:block}
.ol-sugg a{display:flex;gap:12px;align-items:center;padding:9px 10px;border-radius:var(--r2);
  transition:.16s}
.ol-sugg a:hover{background:var(--bone)}
.ol-sugg .ol-sg-ic{width:38px;height:34px;border-radius:8px;background:var(--bone2);
  display:grid;place-items:center;flex-shrink:0}
.ol-sugg .ol-sg-ic svg{width:24px;height:24px;color:var(--mid)}
/* the name and the meta line stack; without display:block they run together
   in the narrower sidebar search */
.ol-sugg a>span{min-width:0}
.ol-sugg .ol-sg-n{display:block;font-size:14px;font-weight:700;color:var(--navy);
  line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ol-sugg .ol-sg-m{display:block}
.ol-sugg .ol-sg-m{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;color:var(--dust);
  margin-top:3px;text-transform:uppercase}
.ol-sugg .ol-sg-p{margin-left:auto;font-weight:800;font-size:14px;color:var(--navy);white-space:nowrap}
.ol-sugg .ol-sg-empty{padding:14px 12px;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--dust)}

/* ==========================================================================
   3. FITMENT PILL — the signature component (B's container, A's colour)
   ========================================================================== */
/* Sits in the flow, not pinned. On the homepage it lands between the hero and
   the counters; elsewhere it sits under the breadcrumb. Padding is even on both
   sides: 12px on the shell, plus 12px on the label, so the optical inset matches
   the status pill's on the right. */
.ol-fitpill{padding:16px 0 0}
.ol-fitpill .ol-inner{background:var(--navy);border-radius:var(--r3);
  padding:10px 12px;display:flex;align-items:center;gap:10px;color:#fff;
  box-shadow:0 16px 36px -22px rgba(0,29,54,.55)}
.ol-fitpill .ol-k{font-family:var(--mono);font-size:11.5px;letter-spacing:.09em;
  text-transform:uppercase;color:#fff;white-space:nowrap;opacity:.85;
  padding:0 6px 0 12px}
.ol-fitpill select{appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.18);border-radius:var(--r3);color:#fff;
  padding:9px 34px 9px 16px;font-size:14px;font-weight:600;cursor:pointer;
  transition:.2s var(--ease);min-width:118px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23fff' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round' opacity='.7'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center}
.ol-fitpill select:hover:not(:disabled){background-color:rgba(255,255,255,.2)}
.ol-fitpill select:disabled{opacity:.4;cursor:not-allowed}
.ol-fitpill select option{color:var(--graphite)}
.ol-fitpill .ol-go{background:var(--red);color:#fff;font-weight:800;font-size:14px;
  letter-spacing:.05em;text-transform:uppercase;padding:12px 22px;border-radius:var(--r3);
  white-space:nowrap;transition:.2s var(--ease)}
.ol-fitpill .ol-go:hover{background:var(--redhover);transform:translateY(-1px)}
.ol-fitpill .ol-st{margin-left:auto;display:flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  color:rgba(255,255,255,.72);white-space:nowrap;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);
  border-radius:var(--r3);padding:10px 18px}
.ol-fitpill .ol-st b{color:#fff;font-weight:500}
.ol-fitpill .ol-clr{font-size:14px;color:rgba(255,255,255,.5);border-bottom:1px solid rgba(255,255,255,.3);
  letter-spacing:.1em;text-transform:uppercase;cursor:pointer}
.ol-fitpill .ol-clr:hover{color:#fff}
.ol-livedot{width:7px;height:7px;border-radius:50%;background:var(--red);flex-shrink:0;
  animation:pulse 2.4s ease-in-out infinite}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(255,31,42,.55)}
  50%{box-shadow:0 0 0 7px rgba(255,31,42,0)}}

/* ==========================================================================
   4. BUTTONS — fully rounded (B), navy/red only (A)
   ========================================================================== */
.ol-btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-weight:800;font-size:13.5px;letter-spacing:.04em;text-transform:uppercase;
  padding:15px 28px;border-radius:var(--r3);border:1.5px solid transparent;
  cursor:pointer;transition:.28s var(--ease);position:relative;overflow:hidden;
  text-align:center}
.ol-btn .ol-arw{transition:.28s var(--ease)}
.ol-btn:hover .ol-arw{transform:translateX(5px)}
.ol-btn-red{background:var(--red);color:#fff}
.ol-btn-red:hover{background:var(--redhover);transform:translateY(-2px);
  box-shadow:0 14px 28px -12px rgba(255,31,42,.55)}
.ol-btn-navy{background:var(--navy);color:#fff}
.ol-btn-navy:hover{transform:translateY(-2px);box-shadow:0 14px 28px -12px rgba(0,45,82,.5)}
.ol-btn-line{border-color:var(--hair);color:var(--navy);background:#fff}
.ol-btn-line:hover{border-color:var(--navy);transform:translateY(-2px);box-shadow:var(--e1)}
.ol-btn-ghost{border-color:rgba(255,255,255,.36);color:#fff}
.ol-btn-ghost:hover{background:rgba(255,255,255,.1)}
.ol-btn-sm{padding:11px 20px;font-size:12.5px}
/* "Ask us" is short; hold a floor so it does not read as stubby next to the
   long outline button beside it */
.ol-callout .ol-btn-sm{min-width:124px}
.ol-btn-block{width:100%}
.ol-btn[disabled]{opacity:.45;pointer-events:none}
.ol-btn-red:after{content:"";position:absolute;top:0;left:-60%;width:40%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.3),transparent);
  transform:skewX(-20deg)}
.ol-btn-red:hover:after{animation:sheen .8s var(--ease)}
@keyframes sheen{to{left:130%}}

/* ==========================================================================
   5. TYPE SCALE
   ========================================================================== */
.ol-lab{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--red);font-weight:500;display:inline-block}
.ol-lab-d{color:var(--dust)}
.ol-lab-n{color:var(--navy)}
.ol-lab-w{color:rgba(255,255,255,.6)}
.ol-spec{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;color:var(--granite)}
.ol-h-hero{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:64px;line-height:.9;
  letter-spacing:-.032em;text-transform:uppercase}
.ol-h-sec{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:40px;line-height:.96;
  letter-spacing:-.025em;text-transform:uppercase;color:var(--navy)}
.ol-h-card{font-weight:800;font-size:16px;line-height:1.24;color:var(--navy)}
/* was 82px: the type pass adds height and the brief wants products higher */
.ol-sec{padding:62px 0}
.ol-sec-tight{padding:36px 0}
.ol-sec-bone{background:var(--bone)}
.ol-sec-pale{background:var(--pale2)}
.ol-sec-navy{background:var(--navy);color:#fff}
.ol-sec-navy .ol-h-sec{color:#fff}
.ol-sec-navy .ol-lead{color:rgba(255,255,255,.74)}
.ol-sechead{display:flex;justify-content:space-between;align-items:flex-end;gap:26px;
  margin-bottom:38px;flex-wrap:wrap}
.ol-sechead .ol-lead{max-width:520px;font-size:14.5px;color:var(--granite);margin-top:14px}
.ol-link{font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--navy);font-weight:700;display:inline-flex;gap:8px;align-items:center;
  padding-bottom:4px;border-bottom:1.5px solid var(--navy);transition:.24s var(--ease)}
.ol-link:hover{gap:14px;color:var(--red);border-color:var(--red)}
.ol-link-w{color:#fff;border-color:rgba(255,255,255,.5)}
.ol-link-w:hover{color:#fff;border-color:#fff}
.ol-crumbs{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dust);padding:22px 0 0}
.ol-crumbs a{color:var(--granite)}
.ol-crumbs a:hover{color:var(--red)}

/* ---- reveal on scroll ----
   Gated behind html.ol-js, which an inline script in the head sets. That gate
   is not decoration: without it .ol-rv{opacity:0} is the CSS default, so if the
   script fails to load, is blocked, or the IntersectionObserver never fires,
   the homepage's category grid -- the most important content on the page after
   the September review -- stays permanently invisible. A reveal is a
   first-scroll affordance and must never be load-bearing for whether content
   can be read at all. With the gate, no JS means no animation and everything
   visible, which is the correct failure. */
.ol-js .ol-rv{opacity:0;transform:translateY(24px);
  transition:opacity .75s var(--ease),transform .75s var(--ease)}
.ol-js .ol-rv.ol-in{opacity:1;transform:none}
.ol-rv-1{transition-delay:.06s}.ol-rv-2{transition-delay:.12s}.ol-rv-3{transition-delay:.18s}
.ol-rv-4{transition-delay:.24s}.ol-rv-5{transition-delay:.30s}.ol-rv-6{transition-delay:.36s}

/* ==========================================================================
   6. HERO — full-bleed band (client, Aug 27) with container-aligned copy
   --------------------------------------------------------------------------
   Originally an inset rounded box, per Direction B. The client asked for
   full-width heroes on every page, so the background now runs to the viewport
   edge while the copy stays on the 1440 container — that keeps the headline
   aligned with the logo and the nav above it instead of drifting out to the
   left edge of a wide monitor. Side radii come off: a band that touches both
   edges cannot have corners. Every other box keeps its 26 px radius, so the
   softer geometry survives everywhere except the four full-bleed bands
   (hero, finder, category head, campaign) and the CTA.
   ========================================================================== */
.ol-hero{padding:0;overflow:hidden}
.ol-herobox{background:var(--deep);border-radius:0;position:relative;
  overflow:hidden;color:#fff;min-height:600px;display:flex;align-items:flex-end}
/* the container is the flex child now, so it has to fill the band */
.ol-herobox>.ol-container,.ol-campbox>.ol-container{width:100%;position:relative}
/* Photographic ground: a loaded 79 Series at golden hour, with a navy scrim so
   the display type keeps its contrast. Scrim is navy-biased, not neutral black,
   so the photograph sits inside the palette rather than beside it. */
.ol-herobox .ol-bg{position:absolute;inset:0;
  background-image:url('img/hero-79-series.jpg');
  background-size:cover;background-position:68% 62%}
.ol-herobox .ol-bg:after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(0,20,38,.94) 0%,rgba(0,20,38,.80) 34%,
             rgba(0,20,38,.30) 66%,rgba(0,29,54,.36) 100%),
             linear-gradient(0deg,rgba(0,15,30,.72) 0%,transparent 46%)}
.ol-hero-in{position:relative;z-index:3;padding:70px 0 62px;max-width:700px}
.ol-hero-in .ol-h-hero{margin:20px 0 22px}
.ol-hero-in .ol-h-hero .ol-ac{color:var(--red)}
.ol-hero-in p{font-size:16px;color:rgba(255,255,255,.78);max-width:430px;margin-bottom:32px}
.ol-hero-cta{display:flex;gap:12px;flex-wrap:wrap}
.ol-hero-veh{display:none}
@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-11px)}}
.ol-hero-terr{display:none}
.ol-hero-badge{position:absolute;right:40px;top:48px;z-index:4;
  background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.2);
  backdrop-filter:blur(8px);border-radius:var(--r3);padding:10px 20px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;text-transform:uppercase;
  display:flex;align-items:center;gap:10px}

/* counters */
.ol-counts{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:14px}
.ol-count{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  padding:24px 26px;transition:.3s var(--ease)}
.ol-count:hover{transform:translateY(-4px);box-shadow:var(--e2);border-color:transparent}
.ol-count .ol-v{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:38px;color:var(--navy);
  line-height:1;letter-spacing:-.03em}
.ol-count .ol-k{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dust);margin-top:10px}

/* ==========================================================================
   6a. HERO BAND + SEARCH, and the homepage category grid  (client, 3 Sep)
   The hero was a 600px photographic screen with a stat row beneath it. It is
   now a band: enough photograph to set the tone, and search plus the first row
   of categories reachable without scrolling. Everything here serves one
   instruction — shorten the path from landing to a product.
   ========================================================================== */
/* 80vh, asked for on 22 Sep. Written as a MINIMUM rather than a fixed height:
   a laptop at 1366x768 gives 614px of hero, and a fixed height would crop the
   headline, the search field and the quick links rather than letting the band
   grow the 40-odd pixels it needs. On anything taller it measures exactly 80vh,
   which is what the instruction was after. */
.ol-heroband{position:relative;background:var(--deep);color:#fff;overflow:hidden;
  min-height:80vh;display:flex;align-items:center;padding:52px 0 46px}
.ol-heroband .ol-bg{position:absolute;inset:0;
  background-image:url('img/hero-79-series.jpg');
  background-size:cover;background-position:62% 46%}
.ol-heroband .ol-bg:after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(0,20,38,.95) 0%,rgba(0,20,38,.86) 46%,
             rgba(0,20,38,.52) 100%)}
.ol-heroband .ol-container{position:relative;z-index:2;width:100%}
.ol-heroband-in{max-width:680px}
.ol-heroband h1{font-family:var(--ol-display);font-weight:400;font-style:italic;text-transform:uppercase;
  font-size:clamp(30px,4.4vw,46px);line-height:1.02;letter-spacing:-.028em}
.ol-heroband p{font-size:17px;line-height:1.55;color:rgba(255,255,255,.82);
  margin:16px 0 26px;max-width:560px}

/* the search field is the hero's main object */
.ol-herosearch{display:flex;align-items:center;gap:10px;background:#fff;
  border-radius:var(--r3);padding:6px 6px 6px 20px;position:relative;
  box-shadow:0 22px 50px -26px rgba(0,0,0,.6);max-width:620px}
.ol-herosearch .ol-mag{width:18px;height:18px;flex-shrink:0;background:currentColor;
  color:var(--dust);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M16.5 16.5 21 21'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M16.5 16.5 21 21'/%3E%3C/svg%3E") center/contain no-repeat}
.ol-herosearch input{flex:1;min-width:0;border:0;outline:0;background:none;
  font:inherit;font-size:16px;color:var(--navy);height:48px}
.ol-herosearch input::placeholder{color:var(--dust)}
.ol-herosearch .ol-btn{flex-shrink:0;height:48px}
/* This field had no focus state of its own -- it was borrowing the white
   ring that section 33 removes, so it gets a real one. The drop shadow is
   restated because a second box-shadow replaces the first. */
.ol-herosearch:focus-within{box-shadow:0 22px 50px -26px rgba(0,0,0,.6),0 0 0 2px var(--navy)}
.ol-herosearch .ol-sugg{top:62px;left:0;right:0;text-align:left}

.ol-heroquick{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:20px}
.ol-heroquick span{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:rgba(255,255,255,.6)}
.ol-heroquick a{font-size:14px;font-weight:600;color:#fff;
  border:1px solid rgba(255,255,255,.26);border-radius:var(--r3);padding:7px 15px;
  transition:.2s var(--ease)}
.ol-heroquick a:hover{background:#fff;color:var(--navy);border-color:#fff}

/* ---- category grid: broad groups that show what is under them ----
   A top-level name alone tells a first-time visitor nothing, so each tile
   lists four of its children. Plain white rather than the old shuffled navy
   colourways: eight saturated tiles fight the product photography that now
   has to lead, and the richness is what leadership pushed back on. */
.ol-catgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.ol-cat{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  padding:20px 20px 16px;position:relative;overflow:hidden;
  display:flex;flex-direction:column;transition:.28s var(--ease)}
.ol-cat:hover{box-shadow:var(--e2)}
/* bottom-right, not top-right: at the top it sat under the part count */
.ol-cat-g{position:absolute;right:-14px;bottom:-12px;width:108px;opacity:.08;
  color:var(--navy);pointer-events:none}
.ol-cat-g svg{width:100%;height:auto}
.ol-cat-h{display:flex;align-items:baseline;gap:8px;position:relative;z-index:2}
.ol-cat-n{font-weight:800;font-size:17px;color:var(--navy);line-height:1.25}
.ol-cat-c{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  color:var(--dust);margin-left:auto;flex-shrink:0}
.ol-cat-h:hover .ol-cat-n{color:var(--red)}
.ol-cat-s{list-style:none;margin:14px 0 0;position:relative;z-index:2;flex:1}
.ol-cat-s li+li{margin-top:2px}
.ol-cat-s a{display:block;font-size:14px;color:var(--granite);padding:3px 0;
  transition:.16s var(--ease)}
.ol-cat-s a:hover{color:var(--navy);transform:translateX(3px)}
/* The base is the light tile: navy on white or pale. The two dark tones
   override it to white below. Red was the original single value for all
   four tones and only ever suited one of them. */
.ol-cat-all{margin-top:14px;font-size:14px;font-weight:700;color:var(--navy);
  display:inline-flex;align-items:center;gap:7px;position:relative;z-index:2}
.ol-cat-all span{transition:transform .24s var(--ease)}
.ol-cat-all:hover span{transform:translateX(4px)}

/* ==========================================================================
   6b. POPULAR VEHICLES — three tiles, no carousel (client, Aug 27)
   The visual entry to the fitment engine, sitting directly under the fitment
   bar: the bar is for the customer who knows their variant, these tiles are for
   the one who would rather point at their truck. Artwork is a silhouette
   placeholder — cut-out photography drops into .ol-pvt .ol-art unchanged.
   ========================================================================== */
.ol-pv{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.ol-pvt{background:#fff;border:1px solid var(--hair);border-radius:var(--rbig);
  padding:26px 26px 24px;display:block;text-align:center;position:relative;
  overflow:hidden;transition:.34s var(--ease)}
.ol-pvt:hover{transform:translateY(-6px);box-shadow:var(--e3);border-color:transparent}
.ol-pvt.ol-on{border-color:var(--red);border-width:1.5px}
.ol-pvt .ol-art{height:146px;display:grid;place-items:center}
.ol-pvt .ol-art svg,.ol-pvt .ol-art img{width:100%;max-width:320px;height:auto;color:var(--navy);
  transition:.5s var(--ease)}
.ol-pvt .ol-art img{max-height:146px;object-fit:contain}
.ol-pvt:hover .ol-art svg,.ol-pvt:hover .ol-art img{transform:translateX(6px) scale(1.04)}
.ol-pvt .ol-mk{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dust)}
.ol-pvt .ol-n{font-weight:800;font-size:20px;line-height:1.1;color:var(--navy);margin-top:9px}
.ol-pvt .ol-c{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--granite);margin-top:11px}
.ol-pvt .ol-cta{margin-top:16px;display:inline-flex;align-items:center;gap:8px;
  font-size:14px;font-weight:700;color:var(--red)}
.ol-pvt .ol-cta span{transition:.28s var(--ease)}
.ol-pvt:hover .ol-cta span{transform:translateX(4px)}
.ol-pvfoot{text-align:center;margin-top:30px}

/* ==========================================================================
   6c. SHOP BY VEHICLE PAGE — the grid behind "Browse the full catalogue"
   Same tile as the homepage trio, four across instead of three. A tile with a
   photograph and a tile with a silhouette are the same shape and the same
   height, so the grid does not go ragged while the shoot list is outstanding.
   ========================================================================== */
.ol-vpage{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.ol-vp{background:#fff;border:1px solid var(--hair);border-radius:var(--rbig);
  padding:20px 20px 18px;display:block;text-align:center;position:relative;
  overflow:hidden;transition:.34s var(--ease)}
.ol-vp:hover{transform:translateY(-5px);box-shadow:var(--e3);border-color:transparent}
.ol-vp.ol-on{border-color:var(--red);border-width:1.5px}
.ol-vp-art{height:118px;display:grid;place-items:center;margin-bottom:4px}
.ol-vp-art svg,.ol-vp-art img{width:100%;max-width:230px;height:auto;
  transition:.5s var(--ease)}
.ol-vp-art img{max-height:118px;object-fit:contain}
/* the silhouette is a placeholder, so it sits back rather than competing with
   the photographed tiles beside it */
.ol-vp:not(.ol-vp-photo) .ol-vp-art svg{color:var(--pale);max-width:200px}
.ol-vp:hover .ol-vp-art img,.ol-vp:hover .ol-vp-art svg{transform:scale(1.05)}
.ol-vp-mk{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dust)}
.ol-vp-n{font-weight:800;font-size:16px;line-height:1.2;color:var(--navy);margin-top:7px}
.ol-vp-c{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--granite);margin-top:8px}
.ol-vp-cta{margin-top:12px;display:inline-flex;align-items:center;gap:6px;
  font-size:14px;font-weight:700;color:var(--red)}
.ol-vp-cta span{transition:transform .26s var(--ease)}
.ol-vp:hover .ol-vp-cta span{transform:translateX(4px)}

/* ==========================================================================
   6d. BRAND LANDING PAGE  (client, Aug 28)
   One template, nine brands. The brand contributes a logo, a tagline and ONE
   accent — exposed as --brand and used on the eyebrow rule and the family
   flags, never on a surface, a button or a heading. That is what keeps nine
   brand pages reading as one site, and it is why the template is reusable
   rather than a per-brand design job.
   ========================================================================== */
:root{--brand:var(--red)}

/* ---- hero: full-bleed, same rule as every other band on the site ---- */
.ol-brhero{position:relative;background:var(--deep);color:#fff;overflow:hidden;
  padding:56px 0 46px}
.ol-brhero-bg{position:absolute;inset:0;
  background:radial-gradient(74% 86% at 84% 18%,rgba(12,67,114,.95),transparent 62%),
             radial-gradient(60% 90% at 4% 100%,rgba(255,31,42,.16),transparent 60%),
             linear-gradient(174deg,#00243f,#000c18)}
.ol-brhero .ol-container{position:relative;z-index:2}
.ol-brhero .ol-container{display:flex;flex-wrap:wrap;align-items:center;gap:30px}
.ol-brhero-in{max-width:600px;flex:1 1 460px}
/* the reference leads with product photography; this is the same move, held to
   the right so the copy keeps the container's left edge */
.ol-brart{flex:0 0 360px;max-width:38%;display:grid;place-items:center}
.ol-brart img{width:100%;height:auto;max-height:330px;object-fit:contain;display:block;
  filter:drop-shadow(0 30px 50px rgba(0,0,0,.5))}
.ol-brmeta{flex:1 1 100%}
/* the brand's real lockup, at a size that respects it */
.ol-brlogo{display:block;max-width:330px;width:100%;height:auto;margin-bottom:22px}
.ol-brtag{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:clamp(26px,4.4vw,40px);
  line-height:1.02;text-transform:uppercase;letter-spacing:-.028em;
  padding-left:16px;border-left:4px solid var(--brand)}
.ol-brlede{font-size:15.5px;color:rgba(255,255,255,.78);margin:22px 0 30px;max-width:580px}
.ol-brmeta{position:relative;z-index:2;display:flex;flex-wrap:wrap;gap:26px;margin-top:34px;
  padding-top:20px;border-top:1px solid rgba(255,255,255,.14);
  font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.6)}

/* ---- "Select your 4WD": their signature band, writing to our garage ---- */
.ol-br4wd{background:var(--navy);padding:16px 0}
.ol-br4wd-in{display:flex;align-items:center;gap:12px;flex-wrap:wrap;color:#fff}
.ol-br4wd .ol-k{font-family:var(--mono);font-size:11.5px;letter-spacing:.09em;
  text-transform:uppercase;color:rgba(255,255,255,.72);padding-right:6px}
.ol-br4wd select{appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.18);border-radius:var(--r3);color:#fff;
  font:inherit;font-size:14px;font-weight:600;padding:11px 38px 11px 18px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23ffffff' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 15px center}
.ol-br4wd select:hover:not(:disabled){background-color:rgba(255,255,255,.2)}
.ol-br4wd select:disabled{opacity:.4;cursor:not-allowed}
.ol-br4wd select option{color:var(--graphite)}
.ol-br4wd .ol-go{background:var(--red);color:#fff;font-weight:800;font-size:14px;
  text-transform:uppercase;letter-spacing:.04em;border-radius:var(--r3);
  padding:12px 22px;transition:.22s var(--ease)}
.ol-br4wd .ol-go:hover{background:var(--redhover);transform:translateY(-1px)}
.ol-br4wd .ol-st{margin-left:auto;display:flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.68);background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.12);border-radius:var(--r3);padding:10px 18px}
.ol-br4wd .ol-st b{color:#fff;font-weight:500}

/* ---- product families ---- */
.ol-brfam{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  padding:24px 22px 22px;position:relative;overflow:hidden;transition:.32s var(--ease)}
.ol-brfam:hover{transform:translateY(-5px);box-shadow:var(--e3);border-color:transparent}
.ol-brfam-art{height:74px;display:grid;place-items:center;margin-bottom:14px}
.ol-brfam-art svg{height:74px;width:auto;color:var(--pale)}
.ol-brfam:hover .ol-brfam-art svg{color:var(--mid)}
.ol-brfam h4{font-weight:800;font-size:17px;line-height:1.25;color:var(--navy)}
.ol-brfam .ol-m{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dust);margin:9px 0 11px}
.ol-brfam p{font-size:14px;color:var(--granite);line-height:1.6}
.ol-brflag{position:absolute;top:14px;right:14px;background:var(--brand);color:var(--graphite);
  font-family:var(--mono);font-size:11.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;border-radius:var(--r3);padding:4px 9px}

/* ---- kits, indexed by vehicle. No fitment badge: the vehicle IS the name. ---- */
.ol-brkitfind input{border:1px solid var(--hair);border-radius:var(--r3);height:42px;
  padding:0 18px;font:inherit;font-size:14px;color:var(--navy);background:#fff;
  outline:0;width:230px;transition:.2s var(--ease)}
.ol-brkitfind input:focus{border-color:var(--navy);box-shadow:var(--e1)}
.ol-brkits{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.ol-brkit{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  overflow:hidden;display:block;transition:.32s var(--ease)}
.ol-brkit:hover{transform:translateY(-5px);box-shadow:var(--e3);border-color:transparent}
.ol-brkit-art{background:var(--bone);height:186px;display:grid;place-items:center;
  padding:16px;overflow:hidden}
/* an explicit pixel cap, not max-height:100% — a percentage does not reliably
   bind on a grid item once max-width has already sized the image, and the
   photography gets clipped */
.ol-brkit-art img{max-width:100%;max-height:154px;width:auto;height:auto;display:block;
  object-fit:contain;transition:.5s var(--ease)}
.ol-brkit:hover .ol-brkit-art img{transform:scale(1.05)}
.ol-brkit-b{padding:18px 18px 20px}
.ol-brkit-n{font-weight:800;font-size:14px;color:var(--navy);line-height:1.3}
.ol-brkit-y{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dust);margin-top:6px}
.ol-brkit-p{font-weight:800;font-size:15px;color:var(--navy);margin-top:12px}
.ol-brkit-p span{font-weight:600;color:var(--granite)}
.ol-brkit-c{margin-top:12px;font-size:14px;font-weight:700;color:var(--red);
  display:inline-flex;align-items:center;gap:6px}
.ol-brkit-c span{transition:transform .24s var(--ease)}
.ol-brkit:hover .ol-brkit-c span{transform:translateX(4px)}
.ol-brkits-none{background:var(--bone);border-radius:var(--r);padding:34px 30px;text-align:center}
.ol-brkits-none h4{font-weight:800;font-size:19px;color:var(--navy)}
.ol-brkits-none p{font-size:14px;color:var(--granite);margin:10px 0 18px}

/* ==========================================================================
   7. CATEGORY GRID — B's icon language, A's palette
   --------------------------------------------------------------------------
   Was a bento of mixed sizes. The client asked for eight equal tiles, 4 × 2
   (Aug 27), so tile size no longer carries merchandising weight — the "most
   fitted" flag and grid position do that job instead. Rows are taller than the
   old bento cell so an equal tile still has presence.
   ========================================================================== */
.ol-bento{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:208px;gap:16px}
.ol-bx{border-radius:var(--r);overflow:hidden;position:relative;background:#fff;
  border:1px solid var(--hair);padding:26px;display:flex;flex-direction:column;
  justify-content:flex-end;transition:.34s var(--ease)}
.ol-bx:hover{transform:translateY(-5px);box-shadow:var(--e3);border-color:transparent}
.ol-bx .ol-g{position:absolute;right:-14px;top:-6px;width:170px;opacity:.15;
  transition:.5s var(--ease);pointer-events:none;color:var(--navy)}
.ol-b-deep .ol-g,.ol-b-navy .ol-g,.ol-b-mid .ol-g{color:#fff}
.ol-b-white .ol-g,.ol-b-pale .ol-g{color:var(--navy)}
.ol-bx:hover .ol-g{transform:scale(1.09) rotate(-3deg);opacity:.22}
.ol-bx .ol-nm{font-weight:800;font-size:18px;line-height:1.2;position:relative;z-index:2}
.ol-bx .ol-ct{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  margin-top:9px;position:relative;z-index:2;opacity:.72}
.ol-bx .ol-go{position:absolute;right:24px;top:24px;width:34px;height:34px;border-radius:50%;
  display:grid;place-items:center;font-size:15px;transition:.3s var(--ease);z-index:3}
.ol-bx:hover .ol-go{transform:rotate(-45deg)}
/* kept for the style guide's record of the original bento; unused on the page */
.ol-b-w2{grid-column:span 2}
.ol-b-h2{grid-row:span 2}
/* the "most fitted" flag is the merchandising lever now that sizes are equal */
.ol-bx .ol-flag{position:relative;z-index:2;display:inline-block;margin-bottom:8px}
/* tile colourways — navy family + red signal only */
.ol-b-deep{background:linear-gradient(150deg,#0C4372,#001D36);color:#fff;border-color:transparent}
.ol-b-deep .ol-go{background:var(--red);color:#fff}
.ol-b-navy{background:var(--navy);color:#fff;border-color:transparent}
.ol-b-navy .ol-go{background:var(--red);color:#fff}
.ol-b-mid{background:linear-gradient(150deg,#12507F,#0C4372);color:#fff;border-color:transparent}
.ol-b-mid .ol-go{background:#fff;color:var(--navy)}
.ol-b-pale{background:var(--pale);border-color:transparent}
.ol-b-pale .ol-nm{color:var(--navy)}.ol-b-pale .ol-ct{color:var(--granite)}
.ol-b-pale .ol-go{background:var(--navy);color:#fff}
.ol-b-white .ol-nm{color:var(--navy)}.ol-b-white .ol-ct{color:var(--granite)}
.ol-b-white .ol-go{background:var(--bone);color:var(--navy)}
.ol-b-white:hover .ol-go{background:var(--navy);color:#fff}

/* ==========================================================================
   8. PRODUCT CARDS — rounded, floating, pill tags, rotating add button
   ========================================================================== */
.ol-grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.ol-grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.ol-grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
.ol-pc{background:#fff;border:1px solid var(--hair);border-radius:var(--r);overflow:hidden;
  display:flex;flex-direction:column;transition:.34s var(--ease);position:relative}
.ol-pc:hover{transform:translateY(-6px);box-shadow:var(--e3);border-color:transparent}
/* Plain white, not the tinted gradient it used to carry.
   The gradient was drawn for the prototype, where every product was a flat SVG
   glyph with nothing behind it. The real catalogue is studio photography cut
   out on white, so a tinted panel put a white rectangle inside a cream one and
   the join read as a gap around every image. object-fit:contain still
   letterboxes a wide light bar in a 4:3 box -- that part is correct, a cropped
   bullbar stops being recognisable -- but on white the letterbox is invisible
   instead of being the first thing you see. */
.ol-pshot{position:relative;aspect-ratio:4/3;background:var(--ol-shot,#fff);
  display:grid;place-items:center;overflow:hidden}
.ol-pshot>svg{width:auto;max-width:68%;max-height:76%;transition:.5s var(--ease)}
.ol-pc:hover .ol-pshot>svg{transform:scale(1.07) translateY(-3px)}
.ol-pshot .ol-code{position:absolute;left:14px;bottom:11px;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em;color:var(--dust)}
.ol-tg{position:absolute;top:13px;left:13px;font-family:var(--mono);font-size:11.5px;
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:5px 11px;
  border-radius:var(--r3);z-index:2}
.ol-tg-red{background:var(--red);color:#fff}
.ol-tg-navy{background:var(--navy);color:#fff}
.ol-tg-pale{background:var(--pale);color:var(--navy)}
.ol-tg-bone{background:var(--bone3);color:var(--granite)}
.ol-wish{position:absolute;top:13px;right:13px;width:30px;height:30px;border-radius:50%;
  background:#fff;border:1px solid var(--hair);display:grid;place-items:center;
  color:var(--dust);font-size:14px;opacity:0;transform:translateY(-6px);
  transition:.3s var(--ease);z-index:3}
.ol-pc:hover .ol-wish,
.ol-wish.ol-on,
.ol-wish:focus-visible{opacity:1;transform:none}
.ol-wish:hover,.ol-wish.ol-on{color:var(--red);border-color:var(--red)}
.ol-quick{position:absolute;left:14px;right:14px;bottom:14px;background:var(--navy);color:#fff;
  text-align:center;font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;
  text-transform:uppercase;padding:10px;border-radius:var(--r3);opacity:0;
  transform:translateY(12px);transition:.32s var(--ease);z-index:3}
.ol-pc:hover .ol-quick{opacity:1;transform:none}
.ol-pb{padding:18px 19px 20px;display:flex;flex-direction:column;flex:1}
.ol-pbrand{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--red);margin-bottom:8px}
/* the brand line is a link where that brand has a landing page */
.ol-pbrand a{color:inherit;border-bottom:1px solid transparent;transition:.16s}
.ol-pbrand a:hover{color:var(--navy);border-bottom-color:currentColor}
.ol-fitl{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em;text-transform:uppercase;color:var(--fit);
  background:rgba(15,123,62,.08);padding:4px 10px;border-radius:var(--r3);
  margin-bottom:10px;align-self:flex-start}
.ol-fitl .ol-d{width:6px;height:6px;border-radius:50%;background:var(--fit)}
.ol-fitl.ol-no{color:var(--granite);background:var(--bone3)}
.ol-fitl.ol-no .ol-d{background:var(--dust)}
.ol-fitl.ol-warn{color:var(--navy);background:var(--pale)}
.ol-fitl.ol-warn .ol-d{background:var(--navy)}
.ol-pname{font-weight:700;font-size:14px;line-height:1.35;color:var(--navy);
  margin-bottom:10px;min-height:37px}
.ol-stars{color:var(--red);font-size:14px;letter-spacing:1px}
.ol-stars span{color:var(--dust);font-family:var(--mono);font-size:11.5px;margin-left:6px;
  letter-spacing:.06em}
.ol-pspec{font-family:var(--mono);font-size:11.5px;color:var(--granite);line-height:1.75;
  padding-top:11px;margin-top:11px;border-top:1px solid var(--hair2)}
.ol-pfoot{margin-top:auto;padding-top:15px;display:flex;align-items:flex-end;
  justify-content:space-between;gap:10px}
.ol-price{font-weight:800;font-size:19px;color:var(--navy);letter-spacing:-.015em}
.ol-price small{display:block;font-family:var(--mono);font-size:11.5px;font-weight:400;
  color:var(--dust);letter-spacing:.06em;text-transform:uppercase;margin-top:4px}
.ol-was{font-size:14px;color:var(--dust);text-decoration:line-through;font-weight:500}
.ol-add{background:var(--bone);color:var(--navy);width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;font-size:17px;flex-shrink:0;transition:.28s var(--ease)}
.ol-pc:hover .ol-add{background:var(--red);color:#fff;transform:rotate(90deg)}
.ol-add.ol-done{background:var(--fit);color:#fff;transform:none!important}

/* ==========================================================================
   9. MARQUEE / BRAND STRIP
   ========================================================================== */
/* Brand strip. The nine partner marks are now knocked out to white and sit
   directly on the navy band — no white tiles (client, Aug 27).
   tools/knockout-logos.ol-py does the recolour. Eight of the nine survive it
   cleanly; three of those come through as reversed badges, because their own
   artwork is white type inside a solid box, so the box becomes the white shape
   and the type reads navy through it. That is a legitimate mono treatment, not
   a defect.
   Tough Dog needed a different measure, not an exception. Its lockup IS a yellow
   shield, so measuring ink as "distance from white" inked the whole shield and
   produced a blob. Measuring it as darkness instead drops the shield and keeps
   what was printed on it, so the wordmark, the paw and the banner become the
   white shape. All nine now sit on the band with no holders.
   This also retires the Direction Plus orange workaround: that mark was always
   the reversed lockup, and reversed is exactly what the band now wants.
   The row is duplicated in the markup so the scroll loops seamlessly. */
.ol-mq{background:var(--navy);color:#fff;padding:20px 0;overflow:hidden;border-radius:var(--r)}
.ol-mq-in{display:flex;align-items:center;white-space:nowrap;animation:slide 34s linear infinite}
.ol-mq-in b{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:26px;text-transform:uppercase;
  padding:0 26px;opacity:.92;letter-spacing:-.02em}
.ol-mq-in i{color:var(--red);font-style:normal;font-size:16px;align-self:center}
.ol-bt{flex:0 0 auto;height:74px;padding:0 24px;display:grid;place-items:center;
  opacity:.88;transition:.3s var(--ease)}
.ol-bt img{max-height:52px;max-width:206px;width:auto;height:auto;display:block;
  object-fit:contain}
.ol-bt:hover{opacity:1;transform:translateY(-3px)}
.ol-mq:hover .ol-mq-in{animation-play-state:paused}

/* ==========================================================================
   10. SPLIT / EDITORIAL / TRUST / JOURNAL
   ========================================================================== */
.ol-split{display:grid;grid-template-columns:1.05fr .95fr;border-radius:var(--r);
  overflow:hidden;border:1px solid var(--hair);background:#fff}
.ol-split .ol-art{position:relative;min-height:420px;
  background:linear-gradient(150deg,#0C4372,#001D36);overflow:hidden}
.ol-split .ol-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  display:block}
.ol-split .ol-cp{padding:56px 52px;display:flex;flex-direction:column;justify-content:center}
.ol-split h3{font-weight:800;font-size:26px;line-height:1.15;color:var(--navy);margin:16px 0}
.ol-split p{color:var(--granite);font-size:14.5px;margin-bottom:26px}

.ol-trust{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.ol-tr{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:26px;
  transition:.3s var(--ease)}
.ol-tr:hover{transform:translateY(-4px);box-shadow:var(--e2);border-color:transparent}
.ol-tr .ol-ic{width:44px;height:44px;border-radius:14px;display:grid;place-items:center;
  margin-bottom:16px;background:var(--pale);color:var(--navy)}
.ol-tr .ol-ic svg{width:21px;height:21px}
.ol-tr .ol-ic-fit{background:rgba(15,123,62,.1);color:var(--fit)}
.ol-tr .ol-ic-red{background:rgba(255,31,42,.09);color:var(--red)}
.ol-tr h4{font-weight:800;font-size:14px;color:var(--navy);margin-bottom:7px}
.ol-tr p{font-size:14px;color:var(--granite);line-height:1.55}

.ol-jc{background:#fff;border:1px solid var(--hair);border-radius:var(--r);overflow:hidden;
  transition:.34s var(--ease);display:block}
.ol-jc:hover{transform:translateY(-5px);box-shadow:var(--e3);border-color:transparent}
.ol-jart{aspect-ratio:16/10;position:relative;overflow:hidden;background:var(--deep)}
.ol-jart svg{transition:.7s var(--ease)}
.ol-jc:hover .ol-jart svg{transform:scale(1.06)}
.ol-jc .ol-b{padding:22px}
.ol-jc h4{font-weight:800;font-size:15px;color:var(--navy);line-height:1.28;margin:10px 0 9px}
.ol-jc p{font-size:14px;color:var(--granite);line-height:1.55}

/* vehicle picker tiles */
.ol-vgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
.ol-vt{border:1px solid var(--hair);border-radius:var(--r);padding:18px 14px;text-align:center;
  background:#fff;transition:.28s var(--ease);display:block}
.ol-vt:hover{transform:translateY(-4px);box-shadow:var(--e2);border-color:transparent}
.ol-vt.ol-on{border-color:var(--red);border-width:1.5px}
.ol-vt svg{width:100%;height:44px;color:var(--pale)}
.ol-vt.ol-on svg{color:#FFD9DB}
.ol-vt .ol-n{font-weight:800;font-size:14px;color:var(--navy);margin-top:8px}
.ol-vt .ol-c{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;color:var(--dust);
  text-transform:uppercase;margin-top:3px}

/* promo boxes */
.ol-promo{position:relative;border-radius:var(--r);overflow:hidden;padding:38px 40px;
  min-height:216px;display:flex;flex-direction:column;justify-content:center;
  transition:.34s var(--ease)}
.ol-promo:hover{transform:translateY(-4px);box-shadow:var(--e3)}
.ol-promo .ol-g{position:absolute;right:-24px;bottom:-16px;width:270px;opacity:.5;
  transition:.5s var(--ease)}
.ol-promo:hover .ol-g{transform:scale(1.05)}
.ol-promo .ol-in{position:relative;z-index:2;max-width:340px}
.ol-promo h3{font-weight:800;font-size:23px;line-height:1.15;margin:12px 0}
.ol-promo-sm{min-height:0;padding:22px 26px;flex-direction:row;align-items:center;gap:18px}
.ol-promo-sm svg{width:80px;flex-shrink:0}
.ol-promo-sm .ol-t{font-weight:800;font-size:16.5px;margin-top:6px}

/* ---- locator control row: search + province on one line ---- */
.ol-locbar{display:grid;grid-template-columns:1fr 210px;gap:12px;align-items:end;
  margin-bottom:18px}
/* input and select render a pixel apart on their own — pin both so the row
   reads as one control, not two that nearly line up */
.ol-locbar input,.ol-locbar .ol-locsel{height:44px;padding-top:0;padding-bottom:0}
.ol-locsel{width:100%;border:1px solid var(--hair);border-radius:var(--r3);
  padding:13px 40px 13px 18px;font-size:14px;background-color:#fff;color:var(--navy);
  font-weight:600;outline:0;appearance:none;-webkit-appearance:none;cursor:pointer;
  transition:.2s;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23002D52' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center}
.ol-locsel:focus{border-color:var(--navy);box-shadow:0 0 0 3px rgba(0,45,82,.08)}

/* ---- fitment centre map (homepage locator, right-hand side) ----
   Deep navy ground, mid-navy landmass, red bubbles sized by centre count.
   Neighbouring countries sit a shade above the ground so the border reads
   without competing with the pins. */
.ol-mapbox{background:var(--deep);border-radius:var(--r);color:#fff;padding:28px 26px 20px;
  height:100%;display:flex;flex-direction:column;justify-content:space-between;
  overflow:hidden}
.ol-maphead{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;
  flex-wrap:wrap}
.ol-mapcount{display:flex;align-items:baseline;gap:12px}
.ol-mapcount b{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:44px;line-height:.9;
  letter-spacing:-.04em;font-variant-numeric:tabular-nums}
.ol-mapcount span{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:rgba(255,255,255,.6)}
.ol-mapsvg{display:block;width:100%;height:auto;margin:16px 0 8px}
.ol-m-nb{fill:#062842;stroke:#10405f;stroke-width:1.6}
.ol-m-za{fill:#0C4372;stroke:#4d8cbf;stroke-width:2.2}
.ol-m-lb{font-family:var(--mono);font-size:16px;letter-spacing:.06em;text-transform:uppercase;
  fill:rgba(255,255,255,.5)}
.ol-m-city{fill:rgba(255,255,255,.5)}
.ol-m-pin{cursor:pointer}
.ol-m-halo{fill:rgba(255,31,42,.18);transition:.3s var(--ease);pointer-events:none}
.ol-m-dot{fill:var(--red);stroke:rgba(255,255,255,.85);stroke-width:2;transition:.3s var(--ease)}
.ol-m-n{font-family:var(--mono);font-weight:700;font-size:18px;fill:#fff;text-anchor:middle;
  pointer-events:none}
.ol-m-pin:hover .ol-m-dot{fill:#fff;stroke:var(--red)}
.ol-m-pin:hover .ol-m-halo{fill:rgba(255,255,255,.22)}
.ol-m-pin.ol-off .ol-m-dot{fill:#2b4b66;stroke:rgba(255,255,255,.2)}
.ol-m-pin.ol-off .ol-m-halo{fill:transparent}
.ol-m-pin.ol-off .ol-m-n{fill:rgba(255,255,255,.45)}
.ol-mapfoot{display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  border-top:1px solid rgba(255,255,255,.12);padding-top:14px;margin-top:8px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:rgba(255,255,255,.55)}
.ol-mapkey{display:inline-flex;align-items:center;gap:8px}
.ol-mapkey i{border-radius:50%;background:var(--red);border:1.5px solid rgba(255,255,255,.8);
  display:block}
.ol-mapkey .ol-k1{width:9px;height:9px}
.ol-mapkey .ol-k2{width:17px;height:17px}
.ol-mapnote{margin-left:auto;color:rgba(255,255,255,.4)}

/* ==========================================================================
   11. FOOTER
   ========================================================================== */
/* The CTA band runs straight into the footer with no white between them
   (client, 27 Aug), so the top corners square off and the margin goes: a
   straight edge and a 26 px radius cannot both be true where they meet. */
.ol-ftr{background:var(--deep);color:rgba(255,255,255,.62);padding:70px 0 0;font-size:14px;
  border-radius:0;margin-top:0}
.ol-ftr .ol-cols{display:grid;grid-template-columns:1.5fr repeat(5,1fr);gap:28px;
  padding-bottom:46px;border-bottom:1px solid var(--hairw)}
.ol-ftr .ol-logo img{height:56px}
.ol-ftr h5{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;margin-bottom:18px}
.ol-ftr ul{list-style:none;display:flex;flex-direction:column;gap:10px}
.ol-ftr ul a{transition:.2s var(--ease);display:inline-block}
.ol-ftr ul a:hover{color:#fff;transform:translateX(3px)}
.ol-ftr .ol-bot{padding:22px 0;display:flex;justify-content:space-between;gap:16px;
  flex-wrap:wrap;font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:rgba(255,255,255,.38)}


/* ==========================================================================
   12. FITMENT FINDER
   ========================================================================== */
.ol-finder{padding:0 0 60px}
/* full-bleed, same rule as the hero — this box IS the Fit page's hero */
.ol-fbox{background:var(--deep);border-radius:0;padding:54px 0 48px;color:#fff;
  position:relative;overflow:hidden}
.ol-fbox .ol-bg{position:absolute;inset:0;
  background:radial-gradient(80% 80% at 78% 26%,rgba(12,67,114,.95),transparent 62%),
             radial-gradient(60% 80% at 8% 100%,rgba(255,31,42,.16),transparent 60%)}
.ol-fbox>*{position:relative;z-index:2}
.ol-prog{height:3px;background:rgba(255,255,255,.14);border-radius:2px;margin:30px 0 26px;
  overflow:hidden}
.ol-prog i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--mid),var(--red));
  border-radius:2px;transition:width .7s var(--ease)}
.ol-steps{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.ol-st{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);
  border-radius:var(--r);padding:22px;transition:.34s var(--ease)}
.ol-st.ol-on{background:#fff;border-color:#fff;color:var(--navy);transform:translateY(-4px);
  box-shadow:0 24px 44px -20px rgba(0,0,0,.5)}
.ol-st .ol-n{font-family:var(--mono);font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--red);margin-bottom:12px}
.ol-st .ol-q{font-weight:800;font-size:14.5px;margin-bottom:14px}
.ol-st .ol-v{font-size:14px;font-weight:600;padding:11px 16px;border-radius:var(--r3);
  background:rgba(0,0,0,.22);border:1px solid rgba(255,255,255,.14);display:flex;
  justify-content:space-between;align-items:center;gap:10px}
.ol-st.ol-on .ol-v{background:var(--bone);border-color:var(--hair);color:var(--navy)}
.ol-st.ol-done .ol-q{opacity:.62}
/* a completed step's value is a button — clicking it reopens that question */
.ol-st .ol-v.ol-vback{width:100%;font-family:inherit;font-size:14px;font-weight:600;
  text-align:left;cursor:pointer;transition:.2s var(--ease)}
.ol-st .ol-v.ol-vback:hover{border-color:var(--red)}
.ol-st.ol-on .ol-v.ol-vback:hover{background:#fff}
/* pills sit on the active step's white card, so give them a tinted ground */
.ol-st.ol-on .ol-pill-l{background:var(--bone)}
.ol-st.ol-on .ol-pill-l:hover{background:#fff;border-color:var(--navy)}
.ol-pills{display:flex;flex-wrap:wrap;gap:8px;margin-top:13px}
.ol-st.ol-on .ol-pills{margin-top:2px}
.ol-pill{border:1px solid rgba(255,255,255,.18);border-radius:var(--r3);padding:8px 16px;
  font-size:11.5px;font-weight:600;background:rgba(255,255,255,.05);
  transition:.24s var(--ease);cursor:pointer}
.ol-pill:hover{background:rgba(255,255,255,.14)}
.ol-pill.ol-on{background:var(--red);border-color:var(--red);color:#fff}
.ol-pill-l{border-color:var(--hair);background:#fff;color:var(--navy)}
.ol-pill-l:hover{background:var(--bone);transform:translateY(-2px)}
.ol-pill-l.ol-on{background:var(--navy);border-color:var(--navy);color:#fff}
.ol-garage{margin-top:26px;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r);padding:24px 28px;
  display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.ol-garage h4{font-weight:800;font-size:18px}
.ol-garage .ol-m{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  color:rgba(255,255,255,.62);margin-top:7px;text-transform:uppercase}
.ol-resultbar{background:var(--bone);border-radius:var(--r);padding:20px 26px;display:flex;
  align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap}

/* ==========================================================================
   13. CATEGORY / ARCHIVE
   ========================================================================== */
.ol-cathead{padding:14px 0 0}
.ol-catbox{background:linear-gradient(140deg,var(--navy),var(--deep));border-radius:0;
  padding:48px 0;color:#fff;position:relative;overflow:hidden}
.ol-catbox>.ol-container{position:relative}
.ol-catbox .ol-g{position:absolute;right:26px;top:-26px;width:250px;opacity:.14}
.ol-catbox p{max-width:560px;color:rgba(255,255,255,.76);font-size:14.5px;margin-top:14px}
.ol-layout{display:grid;grid-template-columns:262px 1fr;gap:30px;padding:30px 0 80px;
  align-items:start}
.ol-fx{background:#fff;border:1px solid var(--hair);border-radius:var(--r);overflow:hidden;
  position:sticky;top:152px}
.ol-fc{border-bottom:1px solid var(--hair2);padding:19px 20px}
.ol-fc:last-child{border-bottom:0}
.ol-fc h5{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--navy);font-weight:700;display:flex;justify-content:space-between;
  margin-bottom:14px}
.ol-fc label{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--granite);
  padding:6px 0;cursor:pointer;transition:.2s var(--ease)}
.ol-fc label:hover{color:var(--navy);transform:translateX(3px)}
.ol-fc input{position:absolute;opacity:0;width:0;height:0}
.ol-cb{width:16px;height:16px;border:1.5px solid var(--dust);border-radius:5px;flex-shrink:0;
  transition:.22s var(--ease);position:relative}
.ol-fc input:checked+.ol-cb{background:var(--red);border-color:var(--red)}
.ol-fc input:checked+.ol-cb:after{content:"";position:absolute;left:4.5px;top:1px;width:4px;
  height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.ol-fc input:focus-visible+.ol-cb{outline:2px solid var(--navy);outline-offset:2px}
.ol-fc .ol-cnt{margin-left:auto;font-family:var(--mono);font-size:11.5px;color:var(--dust)}
.ol-fc-fit{background:linear-gradient(150deg,var(--pale),#fff)}
.ol-tbar{display:flex;justify-content:space-between;align-items:center;gap:16px;
  padding-bottom:20px;border-bottom:1px solid var(--hair);margin-bottom:22px;flex-wrap:wrap}
.ol-chips{display:flex;gap:9px;flex-wrap:wrap;margin-bottom:20px;min-height:1px}
.ol-chip{background:#fff;border:1px solid var(--hair);border-radius:var(--r3);padding:7px 14px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--navy);display:inline-flex;gap:9px;align-items:center;
  transition:.24s var(--ease);cursor:pointer}
.ol-chip:hover{border-color:var(--red);transform:translateY(-2px)}
.ol-chip .ol-x{color:var(--red);display:inline-flex;align-items:center}
.ol-chip-dash{border-style:dashed}
.ol-sortsel{border:1px solid var(--hair);background:#fff;border-radius:var(--r3);
  padding:10px 34px 10px 18px;font-size:14px;font-weight:600;color:var(--navy);
  appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23002D52' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center}
.ol-empty{border:1px dashed var(--hair);border-radius:var(--r);padding:52px 30px;
  text-align:center;color:var(--granite)}
.ol-empty h4{font-weight:800;font-size:19px;color:var(--navy);margin-bottom:10px}
.ol-callout{background:var(--bone);border-radius:var(--r);padding:26px 30px;
  border-left:4px solid var(--red)}

/* ==========================================================================
   14. PDP
   ========================================================================== */
.ol-pdp{display:grid;grid-template-columns:1.05fr .95fr;gap:52px;padding:24px 0 70px;
  align-items:start}
.ol-gal{display:grid;grid-template-columns:80px 1fr;gap:14px}
.ol-thumbs{display:flex;flex-direction:column;gap:10px}
.ol-th{aspect-ratio:1;border:1px solid var(--hair);border-radius:var(--r2);
  background:linear-gradient(155deg,#fff,var(--bone2));display:grid;place-items:center;
  padding:10px;overflow:hidden;transition:.26s var(--ease);cursor:pointer}
.ol-th svg{max-width:100%;max-height:100%;width:auto;color:var(--dust)}
.ol-th:hover{transform:translateY(-2px)}
.ol-th.ol-on{border-color:var(--red);border-width:2px}
.ol-th.ol-on svg{color:var(--navy)}
.ol-mainshot{position:relative;aspect-ratio:1/.9;border:1px solid var(--hair);
  border-radius:var(--r);background:linear-gradient(155deg,#fff,var(--bone2));
  display:grid;place-items:center;overflow:hidden}
.ol-mainshot>svg{width:auto;max-width:60%;max-height:78%;color:var(--navy);
  transition:.5s var(--ease)}
.ol-mainshot .ol-code{position:absolute;left:20px;bottom:18px;font-family:var(--mono);
  font-size:11.5px;color:var(--dust);letter-spacing:.06em}
.ol-mainshot .ol-zoom{position:absolute;right:18px;bottom:18px;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--granite);border:1px solid var(--hair);
  background:#fff;padding:7px 13px;border-radius:var(--r3)}
.ol-pdp h1{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:36px;line-height:.98;
  text-transform:uppercase;color:var(--navy);margin:14px 0 16px;letter-spacing:-.03em}
.ol-pdp .ol-sub{font-size:14.5px;color:var(--granite);margin-bottom:22px}
.ol-pbox{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:26px 28px;
  margin-bottom:18px;box-shadow:var(--e1)}
.ol-pbox .ol-row{display:flex;align-items:flex-end;gap:18px;padding-bottom:20px;
  border-bottom:1px solid var(--hair2);margin-bottom:20px;flex-wrap:wrap}
.ol-pbox .ol-big{font-weight:800;font-size:34px;color:var(--navy);letter-spacing:-.025em;line-height:1}
.ol-fitpanel{border:1.5px solid rgba(15,123,62,.4);
  background:linear-gradient(150deg,rgba(15,123,62,.07),#fff);border-radius:var(--r);
  padding:18px 20px;margin-bottom:18px}
.ol-fitpanel .ol-t{display:flex;align-items:center;gap:10px;font-weight:800;font-size:14px;
  color:var(--fit);margin-bottom:8px}
.ol-fitpanel p{font-size:14px;color:var(--granite)}
.ol-fitpanel .ol-chg{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--navy);border-bottom:1px solid var(--navy);
  margin-top:11px;display:inline-block;cursor:pointer}
.ol-fitpanel.ol-no{border-color:var(--hair);background:var(--bone)}
.ol-fitpanel.ol-no .ol-t{color:var(--granite)}
.ol-fitpanel.ol-warn{border-color:rgba(0,45,82,.35);
  background:linear-gradient(150deg,var(--pale),#fff)}
.ol-fitpanel.ol-warn .ol-t{color:var(--navy)}
.ol-opts h5{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--navy);font-weight:700;margin-bottom:12px}
.ol-buyrow{display:flex;gap:11px;margin:20px 0 12px}
.ol-qty{display:flex;align-items:center;border:1.5px solid var(--hair);border-radius:var(--r3);
  background:#fff;flex-shrink:0}
.ol-qty span{padding:0 14px;font-weight:700;color:var(--navy);min-width:44px;text-align:center}
.ol-qty button{padding:15px 14px;color:var(--dust);font-weight:400;font-size:15px;
  transition:.2s}
.ol-qty button:hover{color:var(--red)}
.ol-assure{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-top:20px}
.ol-assure .ol-a{display:flex;gap:10px;align-items:flex-start;font-size:14px;color:var(--granite);
  line-height:1.45}
.ol-assure .ol-a b{display:block;color:var(--navy);font-size:14px}
.ol-assure .ol-a .ol-tk{color:var(--red);font-weight:800}
.ol-sstrip{background:var(--navy);color:#fff;border-radius:var(--r);padding:24px 26px;
  margin-top:18px}
.ol-sstrip .ol-r{display:flex;justify-content:space-between;gap:20px;padding:10px 0;
  border-bottom:1px solid rgba(255,255,255,.11);font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em}
.ol-sstrip .ol-r:last-child{border-bottom:0}
.ol-sstrip .ol-r span:first-child{color:rgba(255,255,255,.6);text-transform:uppercase;
  white-space:nowrap}
.ol-sstrip .ol-r span:last-child{text-align:right}
.ol-tabs{display:flex;gap:8px;padding:0 0 26px;flex-wrap:wrap}
.ol-tabs button{padding:11px 20px;border-radius:var(--r3);font-family:var(--mono);font-size:11.5px;
  letter-spacing:.07em;text-transform:uppercase;color:var(--granite);background:#fff;
  border:1px solid var(--hair);transition:.24s var(--ease)}
.ol-tabs button:hover{transform:translateY(-2px)}
.ol-tabs button.ol-on{background:var(--navy);color:#fff;border-color:var(--navy);font-weight:700}
.ol-prose{max-width:740px}
.ol-prose p{font-size:14.5px;color:var(--granite);margin-bottom:16px;line-height:1.75}
.ol-prose h4{font-weight:800;color:var(--navy);font-size:15.5px;margin:26px 0 10px}
.ol-prose ul{margin:0 0 16px 18px;color:var(--granite);font-size:14px;line-height:1.85}
.ol-prose table{width:100%;border-collapse:collapse;font-size:14px;margin-bottom:16px}
.ol-prose td{padding:11px 0;border-bottom:1px solid var(--hair2);color:var(--granite)}
.ol-prose td:first-child{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--navy);width:210px;vertical-align:top}
.ol-tabpane{display:none}
.ol-tabpane.ol-on{display:block}

/* review block */
.ol-rev{border:1px solid var(--hair);border-radius:var(--r);padding:22px 24px;background:#fff}
.ol-rev+.ol-rev{margin-top:12px}
.ol-rev .ol-h{display:flex;justify-content:space-between;gap:14px;margin-bottom:9px;flex-wrap:wrap}
.ol-rev b{color:var(--navy);font-size:14px}
.ol-rev p{font-size:14px;color:var(--granite);line-height:1.65}

/* ==========================================================================
   14b. GOOGLE REVIEWS BAND (client, Aug 27)
   The real thing is a Trustindex embed and it cannot run in this demo: the
   file is self-contained and makes no external requests, which is what lets it
   be opened offline and sent as one attachment, and the hosted copy blocks
   third-party scripts outright. So this is the layout at the right size, with
   the content deliberately left as placeholder bars rather than invented
   reviews and an invented star rating — a demo should not put words in a
   customer's mouth or a number on the business that nobody has earned.
   The embed script is recorded in README.ol-md; in WordPress it is a one-line
   HTML widget dropped into this section.
   ========================================================================== */
.ol-gr{display:grid;grid-template-columns:270px 1fr;gap:30px;align-items:start}
.ol-gr-score{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  padding:26px 24px;text-align:center}
/* NB: .ol-num is taken by the campaign stat blocks, hence gr-num */
.ol-gr-score .ol-gr-num{height:40px;display:grid;place-items:center}
.ol-gr-stars{display:flex;gap:4px;justify-content:center;margin-top:14px}
.ol-gr-stars i{width:15px;height:15px;border-radius:3px;background:var(--bone3);
  display:block;font-style:normal}
.ol-gr-score .ol-of{font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--dust);margin-top:14px}
.ol-gr-score .ol-src{margin-top:16px;padding-top:15px;border-top:1px solid var(--hair2);
  font-size:14px;font-weight:700;color:var(--navy)}
.ol-grc{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:22px 22px 24px}
.ol-grc .ol-top{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.ol-grc .ol-av{width:36px;height:36px;border-radius:50%;background:var(--bone2);flex-shrink:0}
.ol-sk{background:var(--bone2);border-radius:4px;height:9px}
.ol-grc .ol-top .ol-sk{height:10px}
.ol-grc .ol-top .ol-sk+.ol-sk{margin-top:7px;height:7px;background:var(--bone)}
.ol-grc .ol-body .ol-sk{margin-top:9px}
.ol-gr-note{margin-top:20px;font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dust);display:flex;align-items:center;gap:10px;
  flex-wrap:wrap}
.ol-gr-note b{color:var(--granite);font-weight:700}
/* the live widget's own container. Trustindex brings its own styling; this only
   gives it room and stops it inheriting anything of ours. */
.ol-ti-host:empty{display:none}
.ol-ti-host.ol-ti-live{margin:0}

/* ==========================================================================
   14c. REQUEST A QUOTE (client, Aug 27)
   The form's job is to be shorter than it looks. The vehicle is carried in from
   the garage rather than asked for again, the system tags are one tap each, and
   only three fields are actually required — everything else is optional context.
   ========================================================================== */
.ol-qwrap{display:grid;grid-template-columns:1fr 340px;gap:30px;align-items:start}
.ol-qform{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  overflow:hidden}
.ol-qsec{padding:26px 30px;border-bottom:1px solid var(--hair2)}
.ol-qsec:last-child{border-bottom:0}
.ol-qsec h3{font-weight:800;font-size:18px;color:var(--navy);margin-bottom:14px}
.ol-qhelp{font-size:14px;color:var(--dust);line-height:1.6}
.ol-qf{display:block;margin-top:14px}
.ol-qf>span{display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dust);margin-bottom:7px}
.ol-qf>span b{color:var(--red)}
.ol-qf input,.ol-qf textarea{width:100%;border:1px solid var(--hair);border-radius:var(--r2);
  padding:12px 15px;font:inherit;font-size:14px;color:var(--navy);background:#fff;
  outline:0;transition:.2s var(--ease)}
.ol-qf textarea{border-radius:var(--r2);resize:vertical;line-height:1.6}
.ol-qf input:focus,.ol-qf textarea:focus{border-color:var(--navy);box-shadow:var(--e1)}
.ol-qf input.ol-bad{border-color:var(--red);background:#FFF7F7}
.ol-qerr{margin-top:16px;background:rgba(255,31,42,.07);border-left:3px solid var(--red);
  border-radius:var(--r2);padding:12px 14px;font-size:14px;font-weight:600;
  color:var(--redhover)}

.ol-qveh-on{display:flex;align-items:center;gap:18px;background:var(--pale);
  border-radius:var(--r);padding:18px 22px}
.ol-qveh-art{width:104px;flex-shrink:0;display:block}
.ol-qveh-art svg,.ol-qveh-art img{width:100%;height:auto;display:block;color:var(--navy)}
.ol-qveh-on .ol-m{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--mid)}
.ol-qveh-on b{display:block;font-size:16px;color:var(--navy);margin-top:5px}
.ol-qveh-on .ol-s{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--granite);margin-top:4px}
.ol-qveh-off{background:var(--bone);border-radius:var(--r);padding:20px 22px}
.ol-qveh-off p{font-size:14px;color:var(--granite);margin-bottom:14px;max-width:440px}

.ol-qtags{display:flex;flex-wrap:wrap;gap:8px;margin:6px 0 4px}
.ol-qtag{border:1px solid var(--hair);border-radius:var(--r3);padding:9px 16px;
  font-size:14px;font-weight:600;color:var(--navy);background:#fff;
  transition:.2s var(--ease)}
.ol-qtag:hover{border-color:var(--navy);transform:translateY(-2px)}
.ol-qtag.ol-on{background:var(--navy);border-color:var(--navy);color:#fff}

.ol-qside{display:flex;flex-direction:column;gap:16px;position:sticky;top:152px}
.ol-qcard{background:#fff;border:1px solid var(--hair);border-radius:var(--r);
  padding:22px 24px}
.ol-qcard-note p{font-size:14px;color:var(--granite);line-height:1.65;margin-top:9px}
.ol-qs-row{display:flex;justify-content:space-between;gap:12px;align-items:baseline;
  padding:11px 0;border-bottom:1px solid var(--hair2);font-size:14px}
.ol-qs-row span{color:var(--granite)}
.ol-qs-row b{color:var(--navy);text-align:right}
.ol-qs-cart{margin-top:12px;background:var(--bone);border-radius:var(--r2);padding:12px 14px}
.ol-qs-line{display:flex;justify-content:space-between;gap:12px;font-size:14px;
  color:var(--granite);padding:4px 0}
.ol-qs-line b{color:var(--navy);white-space:nowrap}

.ol-qdone{padding:44px 34px 40px;text-align:center}
.ol-qdone .ol-tick{width:60px;height:60px;border-radius:50%;background:rgba(15,123,62,.1);
  color:var(--fit);display:grid;place-items:center;margin:0 auto 18px}
.ol-qdone h3{font-weight:800;font-size:23px;color:var(--navy);margin-bottom:12px}
.ol-qdone p{font-size:14px;color:var(--granite);max-width:460px;margin:0 auto;line-height:1.65}

/* ==========================================================================
   15. CART / CHECKOUT
   ========================================================================== */
.ol-cartwrap{display:grid;grid-template-columns:1fr 380px;gap:30px;padding:26px 0 80px;
  align-items:start}
.ol-cline{display:grid;grid-template-columns:104px 1fr auto;gap:20px;align-items:center;
  background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:18px;
  transition:.28s var(--ease)}
.ol-cline+.ol-cline{margin-top:12px}
.ol-cline:hover{box-shadow:var(--e2);border-color:transparent}
.ol-cline .ol-sh{aspect-ratio:1;border-radius:var(--r2);
  background:linear-gradient(155deg,#fff,var(--bone2));display:grid;place-items:center;
  border:1px solid var(--hair2)}
.ol-cline .ol-sh svg{max-width:74%;max-height:74%;color:var(--mid)}
.ol-cline h4{font-weight:700;font-size:14px;color:var(--navy);line-height:1.3;margin-bottom:6px}
.ol-cline .ol-rm{font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dust);border-bottom:1px solid var(--hair);margin-top:10px;display:inline-block;
  cursor:pointer}
.ol-cline .ol-rm:hover{color:var(--red);border-color:var(--red)}
.ol-cline .ol-rt{text-align:right}
.ol-qty-sm{display:inline-flex;align-items:center;border:1.5px solid var(--hair);
  border-radius:var(--r3);background:#fff;margin-bottom:10px}
.ol-qty-sm button{padding:7px 12px;color:var(--dust)}
.ol-qty-sm button:hover{color:var(--red)}
.ol-qty-sm span{padding:0 6px;font-weight:700;color:var(--navy);min-width:30px;text-align:center;
  font-size:14px}
.ol-sumbox{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:26px 28px;
  position:sticky;top:152px;box-shadow:var(--e1)}
.ol-sumbox h3{font-weight:800;font-size:19px;color:var(--navy);margin-bottom:20px}
.ol-sr{display:flex;justify-content:space-between;gap:14px;padding:9px 0;font-size:14px;
  color:var(--granite)}
.ol-sr b{color:var(--navy);font-weight:700}
.ol-sr.ol-tot{border-top:1px solid var(--hair);margin-top:10px;padding-top:16px;font-size:15px}
.ol-sr.ol-tot b{font-size:22px;font-weight:800;letter-spacing:-.02em}
.ol-opt{border:1.5px solid var(--hair);border-radius:var(--r);padding:16px 18px;cursor:pointer;
  transition:.24s var(--ease);display:block;background:#fff}
.ol-opt+.ol-opt{margin-top:10px}
.ol-opt:hover{border-color:var(--navy)}
.ol-opt.ol-on{border-color:var(--red);background:linear-gradient(150deg,rgba(255,31,42,.04),#fff)}
.ol-opt .ol-t{display:flex;align-items:center;gap:11px;font-weight:800;font-size:14px;
  color:var(--navy)}
.ol-opt .ol-radio{width:17px;height:17px;border-radius:50%;border:1.5px solid var(--dust);
  flex-shrink:0;position:relative;transition:.2s}
.ol-opt.ol-on .ol-radio{border-color:var(--red);border-width:5px}
.ol-opt p{font-size:14px;color:var(--granite);margin-top:7px;padding-left:28px}
.ol-opt .ol-pr{margin-left:auto;font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--granite)}
.ol-field{margin-bottom:14px}
.ol-field label{display:block;font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--navy);font-weight:700;margin-bottom:7px}
.ol-field input,.ol-field select,.ol-field textarea{width:100%;border:1px solid var(--hair);
  border-radius:var(--r3);padding:13px 18px;font-size:14px;background:#fff;outline:0;
  transition:.2s}
.ol-field textarea{border-radius:var(--r);min-height:82px;resize:vertical}
.ol-field input:focus,.ol-field select:focus,.ol-field textarea:focus{border-color:var(--navy);
  box-shadow:0 0 0 3px rgba(0,45,82,.08)}
.ol-field .ol-hint{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;color:var(--dust);
  margin-top:6px;text-transform:uppercase}
.ol-row2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.ol-panel{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:28px 30px;
  margin-bottom:16px}
.ol-panel h3{font-weight:800;font-size:18px;color:var(--navy);margin-bottom:18px;display:flex;align-items:center;gap:12px}
.ol-panel h3 .ol-num{width:26px;height:26px;border-radius:50%;background:var(--navy);color:#fff;
  font-family:var(--mono);font-size:11px;font-style:normal;display:grid;place-items:center;
  flex-shrink:0}
.ol-dealer{border:1px solid var(--hair);border-radius:var(--r2);padding:14px 16px;
  display:flex;gap:12px;align-items:center;transition:.22s var(--ease)}
.ol-dealer+.ol-dealer{margin-top:9px}
.ol-dealer[data-d]{cursor:pointer}
.ol-dealer:hover{border-color:var(--navy)}
.ol-dealer.ol-on{border-color:var(--red);background:rgba(255,31,42,.03)}
.ol-dealer .ol-radio{width:15px;height:15px;border-radius:50%;border:1.5px solid var(--dust);
  flex-shrink:0;transition:.2s}
.ol-dealer.ol-on .ol-radio{border-color:var(--red);border-width:4.5px}
.ol-dealer .ol-dpin{width:30px;height:30px;border-radius:50%;background:var(--pale);color:var(--navy);
  display:grid;place-items:center;flex-shrink:0}
.ol-dealer .ol-n{font-weight:700;font-size:14px;color:var(--navy);line-height:1.3}
.ol-dealer .ol-m{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;color:var(--dust);
  text-transform:uppercase;margin-top:5px;line-height:1.5}
.ol-dealer .ol-tel{margin-left:auto;font-family:var(--mono);font-size:11.5px;color:var(--granite);
  white-space:nowrap;border-bottom:1px solid transparent;align-self:flex-start;padding-top:2px}
.ol-dealer .ol-tel:hover{color:var(--red);border-color:var(--red)}
/* The list is long — 58 centres — so it scrolls inside its own panel. */
.ol-loclist{max-height:430px;overflow-y:auto;padding-right:6px;
  -webkit-overflow-scrolling:touch}
.ol-loclist::-webkit-scrollbar{width:8px}
.ol-loclist::-webkit-scrollbar-track{background:var(--bone);border-radius:4px}
.ol-loclist::-webkit-scrollbar-thumb{background:var(--hair);border-radius:4px}
.ol-loclist::-webkit-scrollbar-thumb:hover{background:var(--dust)}
/* The prompt state, shown before anyone has searched. It has to read as an
   invitation rather than a failure, so it borrows the dashed-hairline treatment
   of the empty states but keeps the navy pin and a positive heading. */
/* min-height holds the panel at roughly the height the results list will take,
   so the column does not collapse next to the map and then jump when the first
   search runs */
.ol-locask{border:1px dashed var(--hair);border-radius:var(--rbig);background:var(--bone);
  padding:46px 34px;text-align:center;min-height:410px;
  display:grid;align-content:center;justify-items:center}
.ol-locask svg{color:var(--navy);opacity:.5;margin-bottom:14px}
.ol-locask h4{font-size:16px;font-weight:800;color:var(--navy);letter-spacing:-.01em;
  margin-bottom:8px}
.ol-locask p{font-size:14px;color:var(--granite);max-width:340px;margin:0 auto;line-height:1.6}
.ol-done-box{background:#fff;border:1px solid var(--hair);border-radius:var(--rbig);
  padding:60px 54px;text-align:center;max-width:720px;margin:40px auto 90px;
  box-shadow:var(--e2)}
.ol-done-box .ol-tick{width:74px;height:74px;border-radius:50%;background:rgba(15,123,62,.1);
  color:var(--fit);display:grid;place-items:center;margin:0 auto 24px;font-size:32px}
.ol-done-box h1{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:34px;
  text-transform:uppercase;color:var(--navy);letter-spacing:-.03em;margin-bottom:14px}
.ol-done-box p{color:var(--granite);font-size:14.5px;max-width:460px;margin:0 auto 12px}

/* toast */
.ol-toast{position:fixed;bottom:26px;left:50%;transform:translate(-50%,120%);
  background:var(--navy);color:#fff;border-radius:var(--r3);padding:14px 26px;
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  z-index:300;box-shadow:0 20px 40px -16px rgba(0,29,54,.7);transition:.4s var(--ease);
  display:flex;align-items:center;gap:12px}
.ol-toast.ol-up{transform:translate(-50%,0)}
.ol-toast .ol-d{width:7px;height:7px;border-radius:50%;background:var(--fit)}

/* ==========================================================================
   16. CAMPAIGN PAGE
   ========================================================================== */
.ol-camp{padding:0}
.ol-campbox{border-radius:0;overflow:hidden;position:relative;background:var(--deep);
  color:#fff;min-height:580px;display:flex;align-items:flex-end}
.ol-campbox .ol-bg{position:absolute;inset:0;
  background:radial-gradient(90% 80% at 84% 22%,rgba(12,67,114,.92),transparent 62%),
             radial-gradient(64% 84% at 6% 100%,rgba(255,31,42,.22),transparent 62%),
             linear-gradient(178deg,#00243f,#000a14)}
.ol-campbox .ol-in{position:relative;z-index:3;padding:0 0 62px;max-width:640px}
.ol-campbox .ol-h-hero{font-size:66px}
.ol-kick{display:flex;align-items:center;gap:14px;margin-bottom:8px}
.ol-kick .ol-rule{height:1px;width:54px;background:var(--red)}
.ol-campbox p{max-width:470px;font-size:16px;color:rgba(255,255,255,.8);margin:20px 0 30px}
.ol-campart{position:absolute;right:40px;top:50%;transform:translateY(-50%);width:210px;
  z-index:2;animation:float 10s ease-in-out infinite}
.ol-numrow{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:16px}
.ol-num{border-radius:var(--r);padding:28px 26px;color:#fff;transition:.34s var(--ease)}
.ol-num:hover{transform:translateY(-5px);box-shadow:var(--e3)}
.ol-num:nth-child(1){background:var(--navy)}
.ol-num:nth-child(2){background:var(--mid)}
.ol-num:nth-child(3){background:var(--deep)}
.ol-num:nth-child(4){background:var(--red)}
.ol-num .ol-v{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:40px;line-height:1;
  letter-spacing:-.035em}
.ol-num .ol-k{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
  margin-top:10px;opacity:.85}
.ol-feat{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:stretch}
.ol-fside{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:52px 46px;
  display:flex;flex-direction:column;justify-content:center}
.ol-fside.ol-bone{background:linear-gradient(150deg,var(--bone),var(--bone3));border-color:transparent}
.ol-fvis{border-radius:var(--r);overflow:hidden;position:relative;min-height:430px;
  display:grid;place-items:center;background:linear-gradient(150deg,#0C4372,#001D36)}
.ol-feat h3{font-weight:800;font-size:25px;line-height:1.15;color:var(--navy);margin:16px 0}
.ol-feat p{color:var(--granite);font-size:14.5px;margin-bottom:14px}
.ol-cutlist{list-style:none;display:flex;flex-direction:column;gap:12px;margin-top:10px}
.ol-cutlist li{display:flex;gap:12px;font-size:14px;color:var(--granite);align-items:flex-start}
.ol-cutlist .ol-tk{color:var(--red);font-weight:800}
.ol-route{border:1px solid var(--hair);background:#fff;border-radius:var(--r);padding:26px;
  transition:.32s var(--ease)}
.ol-route:hover{transform:translateY(-5px);box-shadow:var(--e2)}
.ol-route h4{font-weight:800;font-size:16px;margin:12px 0 9px;color:var(--navy)}
.ol-route p{font-size:14px;color:var(--granite);line-height:1.6}
/* Full-bleed CTA (client, Aug 27). Going edge-to-edge would have doubled the
   amount of red on the page, and red is reserved for add-to-cart and primary
   actions — it stops reading as THE action colour once it becomes a large
   background. So the gradient's transition is pushed right: navy holds the
   extra width, red stays a corner, and the final stop sits past 100% so the
   right edge never reaches the pure CTA red. */
.ol-cta-band{background:linear-gradient(102deg,var(--deep) 0%,var(--navy) 56%,var(--red) 116%);
  border-radius:0;color:#fff;padding:52px 0}
.ol-cta-band>.ol-container{display:flex;align-items:center;justify-content:space-between;
  gap:30px;flex-wrap:wrap}
.ol-cta-band h2{font-family:var(--ol-display);font-weight:400;font-style:italic;font-size:34px;
  text-transform:uppercase;line-height:1.02;letter-spacing:-.028em}

/* ==========================================================================
   17. STYLE GUIDE PAGE
   ========================================================================== */
.ol-gwrap{padding:34px 0 90px}
.ol-gcard{background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:38px 40px;
  margin-bottom:18px}
.ol-sws{display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin:18px 0 8px}
.ol-sw{border-radius:var(--r2);overflow:hidden;border:1px solid var(--hair)}
.ol-sw .ol-c{height:72px}
.ol-sw .ol-m{padding:11px 12px;font-family:var(--mono);font-size:11.5px;line-height:1.7;
  color:var(--granite)}
.ol-sw .ol-m b{display:block;color:var(--navy);font-size:14px;letter-spacing:.09em;
  text-transform:uppercase}
.ol-tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.ol-tbl{width:100%;min-width:620px;border-collapse:collapse;margin-top:18px;font-size:14px}
.ol-tbl th{background:var(--navy);color:#fff;text-align:left;padding:12px 14px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;text-transform:uppercase;
  font-weight:500}
.ol-tbl td{padding:12px 14px;border-bottom:1px solid var(--hair);color:var(--granite);
  vertical-align:top}
.ol-tbl td:first-child{color:var(--navy);font-weight:700}
.ol-tbl tr:nth-child(even) td{background:#FBFAF8}
.ol-tbl code{font-family:var(--mono);font-size:11px;background:var(--pale);padding:2px 6px;
  border-radius:4px;color:var(--navy)}
.ol-prin{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:24px}
.ol-prin .ol-p{border-top:2px solid var(--red);padding-top:17px}
.ol-prin .ol-p:nth-child(3n-1){border-color:var(--navy)}
.ol-prin .ol-p:nth-child(3n){border-color:var(--mid)}
.ol-prin h4{font-weight:800;color:var(--navy);font-size:14.5px;margin-bottom:9px}
.ol-prin p{font-size:14px;color:var(--granite);line-height:1.62}
.ol-notebox{background:linear-gradient(140deg,var(--navy),var(--deep));color:#fff;
  border-radius:var(--r);padding:38px 42px;margin-top:8px}
.ol-notebox h3{font-weight:800;font-size:20px;margin-bottom:16px}
.ol-notebox p{color:rgba(255,255,255,.78);font-size:14px;max-width:820px;margin-bottom:12px}
.ol-notebox ul{margin-left:18px;color:rgba(255,255,255,.78);font-size:14px;line-height:1.95}
.ol-notebox b{color:#fff}
.ol-demobar{background:var(--graphite);color:rgba(255,255,255,.7);font-family:var(--mono);
  font-size:11.5px;letter-spacing:.07em;text-transform:uppercase}
.ol-demobar .ol-container{display:flex;align-items:center;gap:16px;height:34px;flex-wrap:wrap}
.ol-demobar b{color:#fff;font-weight:500}
.ol-demobar a{color:var(--red);border-bottom:1px solid rgba(255,31,42,.5)}

/* ==========================================================================
   18. RESPONSIVE
   ========================================================================== */
@media(max-width:1320px){
  /* the wishlist icon is the first thing to go when the nav, the All button and
     the quote pill are all competing for the same row */
  .ol-icohide{display:none}
  .ol-srch{width:168px}
  .ol-nav a{padding:8px 9px;font-size:14px}
}
@media(max-width:1180px){
  .ol-vgrid{grid-template-columns:repeat(3,1fr)}
  .ol-nav a{padding:8px 7px;font-size:14px}
  .ol-srch{display:none}
}
@media(max-width:980px){
  .ol-container{padding:0 22px}
  .ol-grid4,.ol-grid3,.ol-trust,.ol-counts,.ol-steps,.ol-numrow,.ol-sws,.ol-prin,.ol-bento,.ol-vpage,
  .ol-brkits,.ol-catgrid{grid-template-columns:repeat(2,1fr)}
  .ol-layout,.ol-pdp,.ol-split,.ol-feat,.ol-gal,.ol-cartwrap,.ol-row2,.ol-grid2,.ol-gr,.ol-qwrap{grid-template-columns:1fr}
  .ol-bento{grid-auto-rows:178px}
  .ol-b-h2{grid-row:span 1}
  .ol-h-hero{font-size:42px}
  .ol-campbox .ol-h-hero{font-size:44px}
  .ol-hero-veh,.ol-campart,.ol-hero-badge{display:none}
  .ol-hero-in,.ol-campbox .ol-in{padding:44px 0}
  .ol-fbox,.ol-catbox{padding:36px 0}
  .ol-fx{position:static}
  .ol-sumbox,.ol-qside{position:static}
  .ol-split .ol-cp,.ol-fside{padding:36px 30px}
  .ol-cta-band{padding:36px 0}
  .ol-heroband{padding:34px 0 30px}
  .ol-heroband .ol-bg:after{background:linear-gradient(180deg,rgba(0,20,38,.9),rgba(0,20,38,.82))}
  /* Once it wraps, the field is about 114px tall and a 999px radius clamps
     to half of that -- the left and right edges become semicircles curving
     57px inward, and the full-width button underneath escapes the white.
     A wrapped field is a card, so it takes the card radius. */
  .ol-herosearch{padding:6px;flex-wrap:wrap;border-radius:var(--r)}
  .ol-herosearch .ol-mag{display:none}
  .ol-herosearch input{flex:1 1 100%;height:44px;padding:0 12px}
  .ol-herosearch .ol-btn{width:100%}
  /* 62px was measured off the one-row field. Anchored to the box instead,
     or the suggestions open on top of the search button. */
  .ol-herosearch .ol-sugg{top:calc(100% + 6px)}
  .ol-brhero{padding:40px 0 34px}
  .ol-brlogo{max-width:250px}
  .ol-brart{display:none}
  .ol-br4wd .ol-st{margin-left:0;width:100%;justify-content:flex-start}
  .ol-br4wd select{flex:1 1 130px;min-width:0}
  .ol-brkitfind input{width:100%}
  .ol-gcard{padding:26px 22px}
  .ol-nav{display:none}
  /* ...ol-except the copy of it inside the drawer, which IS the navigation at
     this width — same component, no second mobile menu to maintain */
  .ol-side-nav{display:flex;flex-wrap:wrap;gap:6px;padding:16px 20px 4px}
  /* explicit, not inherited: the desktop nav's padding is shrunk at this width
     and the pills would come out cramped */
  .ol-side-nav a{background:var(--bone);color:var(--navy);padding:9px 15px;
    font-size:14px;border-radius:var(--r3)}
  .ol-side-nav a.ol-on{background:var(--navy);color:#fff}
  /* the button keeps its slot but drops the word — the icon is enough here */
  .ol-allbtn{padding:0;width:40px;justify-content:center}
  .ol-allbtn span{display:none}
  .ol-quotebtn{display:none}
  .ol-icohide{display:none}
  .ol-hdr .ol-container{height:66px;gap:12px}
  .ol-fitpill{top:66px}
  .ol-fitpill .ol-inner{flex-wrap:wrap;border-radius:var(--r);padding:14px}
  .ol-fitpill .ol-st{margin-left:0;padding-right:0;width:100%}
  .ol-fitpill select{flex:1;min-width:104px}
  .ol-srch{display:none}
  .ol-cline{grid-template-columns:78px 1fr;gap:14px}
  .ol-cline .ol-rt{grid-column:1/-1;text-align:left;border-top:1px solid var(--hair2);padding-top:12px}
  .ol-sec{padding:44px 0}
  .ol-thumbs{flex-direction:row;overflow:auto}
  .ol-th{width:74px;flex-shrink:0}
  /* the demo bar collapses to one line on small screens */
  .ol-demobar .ol-container{height:auto;min-height:30px;padding:7px 22px;gap:10px;line-height:1.5}
  .ol-demobar .ol-container span:nth-child(2){display:none}
  .ol-demobar a{margin-left:0!important}
}
@media(max-width:620px){
  .ol-grid4,.ol-grid3,.ol-trust,.ol-counts,.ol-steps,.ol-numrow,.ol-sws,.ol-prin,.ol-bento,.ol-vgrid,.ol-assure,.ol-pv,
  .ol-catgrid{grid-template-columns:1fr}
  .ol-vpage,.ol-brkits{grid-template-columns:repeat(2,1fr)}
  .ol-b-w2{grid-column:span 1}
  .ol-h-hero{font-size:34px}
  .ol-h-sec{font-size:29px}
  .ol-ftr .ol-cols{grid-template-columns:1fr 1fr}
}
@media(max-width:900px){
  .ol-herobox .ol-bg{background-image:url('img/hero-79-series-sm.jpg');background-position:64% 58%}
  /* at this width the phone number crushes the address, so only it wraps —
     the pin and the name stay on one line together */
  .ol-dealer{flex-wrap:wrap;row-gap:8px}
  .ol-dealer>div{flex:1 1 0;min-width:0}
  .ol-dealer .ol-tel{flex:0 0 100%;margin-left:42px;padding-top:0}
  .ol-dealer .ol-m{margin-top:4px}
  .ol-locbar{grid-template-columns:1fr}
  .ol-bt{height:64px;padding:0 16px}
  .ol-bt img{max-height:36px;max-width:170px}
  .ol-split .ol-art{min-height:260px}
  .ol-mapbox{padding:22px 20px 16px}
  .ol-mapcount b{font-size:34px}
  .ol-mapnote{display:none}
  .ol-herobox{min-height:480px}
  .ol-logo img{height:42px}
}
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .ol-rv{opacity:1;transform:none}
}

/* ==========================================================================
   19. ADDENDA FOR THE WORDPRESS BUILD
   Rules the standalone demo did not need because its chrome was generated by
   JavaScript. On the live site the header and footer are Elementor widgets, so
   a few classes are new here rather than ported.
   ========================================================================== */

/* The icon sprite's <use> wrapper. Sized inline per call; this only stops it
   sitting on the text baseline and inheriting a stray stroke. */
.ol-i{display:block;flex:0 0 auto;fill:none;stroke:currentColor}

/* A nav item that leaves the site says so. The Explore tab points at a
   separate application, and a navigation item that silently navigates away
   is a trap rather than a link. */
.ol-navext{display:inline-flex;align-items:center;gap:5px}
.ol-navext:hover .ol-extico{opacity:1}

/* Shown in the drawer only while the eight system categories are still being
   set up, so an empty panel reads as "not finished" rather than "broken". */
.ol-side-note{font-size:14px;color:var(--granite);padding:4px 2px 14px;line-height:1.6}

/* ---- product card, real photography ----
   The demo drew products as flat SVG glyphs, so .ol-pshot only ever styled a
   direct <svg> child. 391 of the 399 live products have a real featured image,
   so the <img> needs the same treatment: contained rather than cropped,
   because a bullbar cropped to fill a 4:3 box stops being recognisable. */
.ol-pshot img{width:100%;height:100%;object-fit:contain;padding:12px;
  transition:.5s var(--ease)}
.ol-pc:hover .ol-pshot img{transform:scale(1.05) translateY(-3px)}
.ol-pshot .ol-pshot-ph{width:96px;height:96px;color:var(--dust);opacity:.35}

/* Visually hidden, still read aloud.
   Defined here rather than relied on from WooCommerce's or the parent theme's
   stylesheet, because the product card prints WooCommerce's price_html, and
   that includes a screen-reader-only "Price range: X through Y" span. If
   nothing hides it the card reads "R34 755,00 - R56 235,00Price range: R34
   755,00 through R56 235,00". Owning the rule means the card cannot be broken
   by another plugin's CSS load order. */
.screen-reader-text,
.ol-site .screen-reader-text{position:absolute!important;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;border:0}
.screen-reader-text:focus{position:static!important;width:auto;height:auto;
  margin:0;overflow:visible;clip:auto;clip-path:none;white-space:normal}

/* WooCommerce's own price markup inside our card. */
.ol-price .woocommerce-Price-amount{white-space:nowrap}
.ol-price del{color:var(--dust);font-weight:500;font-size:14px;margin-right:6px}
.ol-price ins{text-decoration:none}

/* .ol-pname is an anchor here rather than the demo's div, so it needs to be a
   block for its min-height to apply and keep every card the same height. */
a.ol-pname{display:block}
a.ol-pname:hover{color:var(--red)}

/* The rail scrolls horizontally rather than wrapping: a best-of row that
   reflows to two ragged lines stops reading as a row. */
.ol-rail{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(258px,1fr);
  gap:18px;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x proximity;
  scroll-behavior:smooth;padding:4px 0 10px}
.ol-rail>*{scroll-snap-align:start}

/* The scrollbar is gone, not restyled -- see section 30 for what replaced it.
   overflow-y is pinned to hidden on purpose: setting overflow-x to auto makes
   the other axis compute to auto as well, which is where the second, vertical
   scrollbar down the right of the rail came from. The 4px of top padding is
   the room the cards hover shadow needs now that the box clips. */
.ol-rail{scrollbar-width:none;-ms-overflow-style:none}
.ol-rail::-webkit-scrollbar{width:0;height:0;display:none}

/* Elementor wraps every widget in its own div. Left alone that wrapper adds a
   stacking context and a width the full-bleed header and footer bands have to
   fight, so it is flattened here once rather than per template. */
.elementor-widget-ol-site-header,
.elementor-widget-ol-site-footer{width:100%}
.elementor-widget-ol-site-header .elementor-widget-container,
.elementor-widget-ol-site-footer .elementor-widget-container{width:100%}

/* The editor renders widgets inside an iframe with its own body margin; the
   footer band is full-bleed and would otherwise show a white gutter there. */
.elementor-editor-active .ol-ftr,
.elementor-editor-active .ol-hdr{margin-left:0;margin-right:0}

/* ==========================================================================
   19b. HEADINGS UNDER HELLO ELEMENTOR
   Site-wide, not specific to any one band. This is a correction, so it is
   worth saying exactly what it corrects.

   Hello Elementor ships assets/css/reset.css, which is enqueued on every page
   and contains one rule:

     h1,h2,h3,h4,h5,h6{color:inherit;font-family:inherit;font-weight:500;
       line-height:1.2;margin-block-end:1rem;margin-block-start:.5rem}

   Three things follow from it, and all three move the build away from the
   signed-off design.

   1. WEIGHT. Not one of the twelve rules in this stylesheet that uses
      var(--ol-display) declares a font-weight, so Hello's 500 is what every OL
      heading computes to -- measured, not assumed. Archivo Black ships a
      single 400 cut, so the browser is being asked for a weight that does not
      exist. Chromium resolves that to the 400 face and draws it correctly, so
      nothing looks wrong today; Safari and Firefox are freer with synthetic
      bold, and the day anyone adds an Archivo Black 700 file or sets a weight
      in the Elementor kit, every heading on the site changes at once. It is
      pinned here rather than left to that.

      The numerals are the case where it already bites: .ol-mapcount b,
      .ol-mq-in b and the .ol-v counters are <b> elements, so their UA default
      is bold -- they have been asking for 700 Archivo Black all along.

   2. MARGINS. This is the visible one. `margin-block-start:.5rem` and
      `margin-block-end:1rem` beat this file's `*{margin:0}` on specificity
      (0-0-1 against 0-0-0) no matter which file loads first. So every heading
      on the site carries 8px above it, and every heading that does not set its
      own bottom margin carries 16px below. That includes .ol-h-sec,
      .ol-heroband h1 and .ol-cta-band h2 -- the three largest headings there
      are, and the ones the design spaces most tightly.

   3. FAMILY. `font-family:inherit` means a heading with no OL class renders in
      the body face. Every heading the theme itself writes is covered by a
      class or a descendant rule, but an Elementor Heading widget the team
      drops on a page is not, and neither is a WooCommerce or blog title. Those
      get brand defaults below.

   ON SPECIFICITY, because it is the whole trick here
   The two resets use `.ol-site :where(...)`, which computes as a single class
   (0-1-0): above Hello's bare tags, and below every intentional rule in this
   stylesheet -- `.ol-tr h4`, `.ol-ftr h5`, `.ol-hero-in .ol-h-hero` and the
   rest are 0-1-1 or higher and keep their own margins untouched. Matching
   Hello's specificity and winning on order instead would have overridden those
   as well, which is the trap: `margin-block-end` and `margin-bottom` are the
   same property to the cascade, so a blunt reset at the end of the file wipes
   the 7px under a promise title and the 18px under a footer column head.

   Deliberately NOT set on the bare-heading defaults: color, font-size,
   line-height and letter-spacing.
     - color, because .ol-cta-band h2 sits on a dark band and takes its colour
       by inheritance. A default of var(--navy) here would render it navy on
       navy. It inherits, exactly as Hello had it.
     - the other three, because .ol-h-sec is also 0-1-0 and comes earlier in
       the file, so anything set here at the same specificity would silently
       replace its line-height of .96 and its -.025em tracking.
   ========================================================================== */

/* 1. the weight, pinned on every rule that uses the display face */
.ol-side-ttl,
.ol-h-hero,
.ol-h-sec,
.ol-count .ol-v,
.ol-heroband h1,
.ol-brtag,
.ol-mq-in b,
.ol-mapcount b,
.ol-pdp h1,
.ol-done-box h1,
.ol-num .ol-v,
.ol-cta-band h2{
  font-weight:400;
  /* and if a weight ever does leak past the line above, still never fake it */
  font-synthesis-weight:none}

/* 2. Hello's heading margins, removed without touching the ones we set */
.ol-site :where(h1,h2,h3,h4,h5,h6){margin-block-start:0;margin-block-end:0}

/* 3. brand defaults for a heading with no OL class -- an Elementor Heading
      widget, a WooCommerce title, a blog post title. h1 and h2 take the
      display face because they are page and section headings by role; h3
      downwards take Archivo 800 sentence-case, which is the .ol-h-card
      treatment and what the 3 Sep readability pass restricted the display
      face in favour of. */
.ol-site :where(h1,h2){font-family:var(--ol-display);font-style:italic;font-weight:400;
  font-synthesis-weight:none;text-transform:uppercase}
.ol-site :where(h3,h4,h5,h6){font-family:var(--body);font-weight:800;
  font-synthesis-weight:none}

/* ...except inside article body copy, where an h2 is a subheading in running
   text rather than a section head. Uppercase italic Archivo Black is precisely
   what the 3 Sep readability pass took OUT of that role: uppercase removes
   word-shape and italic removes it again, and a subhead in a 600-word article
   is the place that costs most. The Journal template is Phase 6, so this
   guards a page that does not exist yet -- three lines now against finding it
   the hard way later. */
.ol-site :where(.entry-content,.elementor-widget-theme-post-content)
  :where(h2,h3,h4,h5,h6){font-family:var(--body);font-style:normal;font-weight:800;
  text-transform:none}

/* .ol-ftr h5 sets a mono face, a size and a colour but no weight, so in the
   prototype it rendered at the browser's own bold for <h5> -- 700, which
   JetBrains Mono actually ships. Under the defaults above it would have picked
   up 800, a weight that family does not have. Stated explicitly, because a
   design that depends on a UA default is a design that breaks the first time a
   theme resets it, which is exactly what happened here. */
.ol-ftr h5{font-weight:700}

/* ==========================================================================
   19c. POPULAR VEHICLES + CENTRE LOOKUP  (WordPress build)
   Appended rather than edited into sections 6b and 10, so the namespaced
   transform of the prototype's stylesheet stays a straight transform and this
   file's history shows what the WordPress build actually added.
   ========================================================================== */

/* ---- the vehicle silhouette ----
   The prototype inlined its silhouettes with a per-call class. Here they come
   out of the sprite through ol_vehicle_glyph(), so the sizing that used to sit
   on .pvt .art svg lives on the glyph itself and works wherever it is used. */
.ol-vsil{width:100%;max-width:320px;height:auto;color:var(--navy)}

/* A silhouette is a placeholder for cut-out photography, so it steps back
   rather than competing with a photographed tile beside it in the same row --
   but not so far back that a row of three unphotographed tiles reads as three
   empty boxes. #B9C7D6 is a deliberate midpoint: legible as a drawing of a
   bakkie, obviously not a photograph. --pale was tried first and disappeared. */
.ol-pvt-ph .ol-art .ol-vsil{color:#B9C7D6;max-width:290px}

/* ---- the centre lookup: two columns that end level ----
   The list column is scoped by its own class rather than by .ol-rv. Targeting
   .ol-grid2>.ol-rv turned the MAP column into a flex row too -- both columns
   carry .ol-rv -- and .ol-mapbox then shrank to its content width, 488px inside
   a 671px column. Worth naming: it looked like a grid bug for a while. */
.ol-loccol{display:flex}
.ol-loccol>.ol-panel{display:flex;flex-direction:column;flex:1}
.ol-loc{display:flex;flex-direction:column;flex:1}

/* The map's height comes from the SVG's aspect ratio, so it is the taller
   column. Letting the list fill its panel means the prompt state and the
   results sit in a box the height of the map instead of leaving a band of
   white under the panel. max-height goes because flex now owns the height;
   the list still scrolls, it just scrolls at the map's height. */
.ol-loc .ol-loclist{flex:1;max-height:none;min-height:0}
.ol-loc .ol-locask{min-height:0;height:100%}
.ol-loc-mapfirst .ol-locmap{order:-1}

/* One column, no map: the panel would otherwise run the full container width
   and the search row would look lost in it. */
.ol-loc-solo{max-width:760px}

/* ---- the province select's dropdown arrow ----
   A real bug inherited from the prototype, not a new rule. .ol-locsel paints
   its own chevron as a background-image, but the select sits inside .ol-field,
   and `.ol-field select` (section 15) sets the `background` SHORTHAND, which
   resets background-image to none -- and it both outranks .ol-locsel on
   specificity and comes later in the file. So the province select has been
   rendering with appearance:none and no chevron at all: a pill with no hint
   that it opens. Restated here at a specificity that wins, using longhands
   only, so the next shorthand somewhere else cannot silently erase it again. */
.ol-field select.ol-locsel{
  background-color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23002D52' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 16px center;
  padding-right:40px}

/* ---- lookup states ----
   The list is aria-live, so it announces changes; aria-busy plus a dim is the
   visible half of the same message while a query is in flight. */
.ol-loclist[aria-busy="true"]{opacity:.55}
.ol-locpick{margin-bottom:14px}

/* A centre whose number has not been imported yet renders as plain text, never
   as a tel: link -- a dial link that dials nothing is worse than no link, and
   an invented number is worse than both. Same metrics as .ol-tel so the rows
   stay on one grid whether the number is there or not. */
.ol-tel-tbc{margin-left:auto;font-family:var(--mono);font-size:11.5px;
  letter-spacing:.06em;color:var(--dust);white-space:nowrap;align-self:flex-start;
  padding-top:2px;text-transform:uppercase}

/* The placeholder marker on a seeded row. Amber rather than red: this is
   "not confirmed yet", not "broken".

   The word itself is rendered by the script, not by a CSS `content` string.
   Text in a stylesheet cannot be translated, and this site has a fair chance of
   wanting Afrikaans. */
.ol-provtag{margin-left:8px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;
  color:#996800;background:rgba(153,104,0,.09);border-radius:20px;padding:2px 7px;
  vertical-align:1px;font-weight:700;white-space:nowrap}

/* The retry in the failure state is a button, because it performs an action
   rather than going anywhere -- so it needs the anchor styling of .ol-link
   without the button chrome the browser adds. */
.ol-empty button.ol-link{background:none;border:0;padding:0;font:inherit;
  color:var(--red);cursor:pointer;text-decoration:underline;text-underline-offset:2px}

/* Map bubbles are buttons, so they need a visible focus ring. SVG cannot take
   a box-shadow, so the ring is drawn on the halo circle instead.

   The selector has to carry [tabindex] to outrank Hello Elementor's own focus
   style, which is
     [tabindex]:not([tabindex="-1"]):focus-visible{box-shadow:0 0 0 4px #fff;
       outline:2px solid #000;outline-offset:2px}
   at 0-3-0. A plain .ol-m-pin:focus-visible loses to that, and the bubble then
   gets a black outline and a white glow on top of the halo below -- two focus
   rings, one of them off-palette on a navy map. The dashed white halo is a
   clear indicator in its own right against that ground, and the list beside
   the map is the accessible route to the same filter either way. */
.ol-m-pin[tabindex]:not([tabindex="-1"]):focus,
.ol-m-pin[tabindex]:not([tabindex="-1"]):focus-visible{outline:none;box-shadow:none}
.ol-m-pin:focus-visible .ol-m-halo{fill:rgba(255,255,255,.30);
  stroke:#fff;stroke-width:2;stroke-dasharray:3 3}

@media (max-width:900px){
  /* Stacked, the map no longer sets the row height, so the list goes back to
     its own scroll height rather than stretching to nothing. */
  .ol-loc .ol-loclist{max-height:430px}
  .ol-loc .ol-locask{min-height:340px;height:auto}
  .ol-loc-mapfirst .ol-locmap{order:0}
}

/* ==========================================================================
   20. THE CATALOGUE  (Phase 3, WordPress build)

   Section 13 already carries the archive's shell -- .ol-layout, .ol-fx, .ol-fc,
   .ol-cb, .ol-tbar, .ol-chips, .ol-chip, .ol-sortsel, .ol-empty, .ol-callout,
   .ol-cathead, .ol-catbox -- transformed from the prototype and untouched here.
   What follows is only what the WordPress build genuinely adds: the parts of a
   real catalogue the prototype's nine fake products never needed. Pagination,
   a filter rail that has to work with the script blocked, a rail that has to
   collapse on a phone, and the vehicle notice.
   ========================================================================== */

/* ---- the grid column ----
   min-width:0 is load-bearing and it is not obvious. A `1fr` grid track refuses
   to shrink below its content's min-content width, and a product card holding
   "Tough Dog Foam Cell Front Shock Absorber Toyota Land Cruiser 79 Series" has
   a wide min-content. Without this the right column pushes the layout past the
   container and the whole page scrolls sideways on a laptop -- which reads as a
   broken grid rather than as one long product name. */
.ol-catmain{min-width:0}

/* ---- the header band ----
   .ol-h-hero is 64px, which is right for a homepage hero and wrong for a
   category name that can run to "Suspension & Lift" over two lines inside a
   48px-padded band. The prototype set the same clamp inline; here it is a class
   so the brand and search heads get it too. */
.ol-cattitle{font-size:clamp(30px,7vw,44px);margin-top:12px}

/* The brand mark, where the term has one. The nine transferred marks are white
   knockouts, which is exactly right on the navy band and the reason they can be
   used here at all -- a dark-on-white logo would need a plate behind it. */
.ol-catlogo{margin-bottom:18px}
.ol-catlogo img{height:38px;width:auto;max-width:230px;object-fit:contain;
  object-position:left center}

/* ---- the facet rail ----
   Sticky, and capped so it cannot run past the fold. Four facets on the shop
   root come to roughly thirty-five rows; without the cap the bottom of the rail
   sits below the viewport with no way to reach it, because a sticky element
   scrolls with nothing. overscroll-behavior stops the page from taking over the
   scroll the moment the rail hits its end. */
.ol-fx{max-height:calc(100vh - 172px);overflow-y:auto;overscroll-behavior:contain}
.ol-fx::-webkit-scrollbar{width:8px}
.ol-fx::-webkit-scrollbar-thumb{background:var(--hair);border-radius:8px}
.ol-fx{scrollbar-width:thin;scrollbar-color:var(--hair) transparent}

/* The option count in the block heading, in the slot the prototype's "-" used. */
.ol-fc h5 span{font-family:var(--mono);font-size:10.5px;color:var(--dust);font-weight:400}

/* The label text between the box and the count. flex:1 rather than a margin on
   the count, so a long brand name wraps inside its own column instead of
   pushing the number off the edge of the rail. */
.ol-fc-l{flex:1;min-width:0;line-height:1.35}

/* An option's count sits at the top of a wrapped label rather than centred
   against two lines of text, which otherwise floats it in the gap. */
.ol-fc label{align-items:flex-start}
.ol-fc .ol-cb{margin-top:2px}
.ol-fc .ol-cnt{margin-top:1px}

/* A sentence in the body face, not a mono micro-label. It started as mono at
   10px uppercase, matching the facet headings -- but the headings are labels of
   two or three words and this is a two-line instruction. Section 1 of this
   stylesheet already records that the mono micro-labels at 8.5-10px were the
   readability problem worth fixing, and uppercase strips the word shapes a
   reader scans by. 14px is the stated floor for secondary text; this sits just
   under it at 13px because it is help text inside a 262px rail. */
.ol-fx-note{font-size:13px;line-height:1.6;color:var(--granite);margin:0}

/* The Apply row. Present for the no-script path and hidden once the script
   confirms itself, because with JS a checkbox navigates on change and a button
   that submits the state you are already looking at is a dead control. It is
   hidden by html.ol-js rather than removed by script, so the failure mode is a
   visible working button rather than no way to apply anything. */
.ol-fx-act{display:flex;flex-direction:column;gap:12px;align-items:center;
  background:var(--bone)}
html.ol-js .ol-fx-act .ol-btn{display:none}
.ol-fx-clear{font-family:var(--mono);font-size:11px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--red);text-decoration:underline;
  text-underline-offset:3px}

/* ---- the mobile filter button ----
   Under 900px section 18 already drops .ol-fx out of sticky and stacks it above
   the grid. Five blocks of filters between the page title and the first product
   is the whole first screen, so the rail collapses behind its own button --
   again gated on html.ol-js, so with the script blocked every filter is simply
   visible and reachable. */
.ol-fx-toggle{display:none;width:100%;align-items:center;gap:10px;
  background:var(--navy);color:#fff;border:0;padding:15px 20px;cursor:pointer;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase}
/* White on the navy bar, not red. Red on this site means act -- add to cart,
   the primary CTA, the arrow on a dark tile -- and this is a count of how many
   filters are on, which is a state. Using red here would have been the fourth
   red thing on the page competing with the one that matters. */
.ol-fx-toggle em{margin-left:auto;font-style:normal;background:#fff;color:var(--navy);
  border-radius:var(--r3);min-width:22px;height:22px;display:grid;place-items:center;
  font-size:11px;font-weight:800;padding:0 6px}
.ol-fx-toggle .ol-i{color:#fff;flex-shrink:0}

/* ---- the toolbar ----
   The count is a sentence, not a number: "25-48 of 399 parts" answers the
   question a bare 24 does not. */
.ol-tcount b{color:var(--navy);font-size:15px;font-weight:800}
.ol-tcount .ol-spec{margin-left:8px}
.ol-sortform{display:flex;gap:10px;align-items:center}

/* ---- the vehicle notice ----
   Amber for "not mapped yet", pale navy for "mapped, here is the coverage".
   The same colour language the placeholder centre rows use, for the same
   reason: this is incomplete data, not a failure. */
.ol-shopnote{display:flex;gap:14px;align-items:center;background:var(--pale);
  border:1px solid var(--hair);border-left:4px solid var(--navy);
  border-radius:var(--r);padding:16px 20px;margin-bottom:22px;flex-wrap:wrap}
.ol-shopnote-warn{background:rgba(153,104,0,.06);border-left-color:#996800}
.ol-shopnote-ic{color:var(--navy);display:grid;place-items:center;flex-shrink:0}
.ol-shopnote-warn .ol-shopnote-ic{color:#996800}
.ol-shopnote div{flex:1;min-width:220px}
.ol-shopnote b{display:block;color:var(--navy);font-size:14.5px;font-weight:800}
.ol-shopnote span{display:block;margin-top:3px;font-size:13.5px;color:var(--granite);
  line-height:1.6}
.ol-shopnote .ol-btn{flex-shrink:0}

/* ---- pagination ----
   New: the prototype had nine products and never needed a second page.

   Fully rounded, not the 12px I reached for first. The design system states
   one radius scale -- 18px panels, 12px small tiles and thumbs, 999px EVERY
   control -- and a page number is a control. My argument for 12px was that a
   row of circles reads as unrelated controls rather than one scale; that is a
   preference, and the stated rule outranks it. At 40px square a single digit
   lands as a circle and Previous/Next as pills, which is the same shape
   language as every other control on the site. */
.ol-pag{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:40px;
  padding-top:26px;border-top:1px solid var(--hair)}
.ol-pag .page-numbers{min-width:40px;height:40px;padding:0 13px;display:inline-grid;
  place-items:center;border:1px solid var(--hair);border-radius:var(--r3);background:#fff;
  color:var(--navy);font-size:14px;font-weight:600;transition:.22s var(--ease)}
.ol-pag a.page-numbers:hover{border-color:var(--red);color:var(--red);
  transform:translateY(-2px)}
.ol-pag .page-numbers.current{background:var(--navy);border-color:var(--navy);color:#fff}
.ol-pag .page-numbers.dots{border-color:transparent;background:none;color:var(--dust);
  min-width:24px;padding:0}
.ol-pag .prev,.ol-pag .next{font-family:var(--mono);font-size:11px;letter-spacing:.07em;
  text-transform:uppercase}
.ol-pag-of{margin-left:auto;font-family:var(--mono);font-size:11px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dust)}

/* ---- the empty state and the callout ----
   Both carried inline styles in the prototype. Moved to classes because both
   now render from PHP in three variants, and three copies of the same inline
   style is three places to forget. */
.ol-empty p{max-width:520px;margin:0 auto;font-size:13.5px;line-height:1.7}
.ol-empty-act{margin-top:20px;display:flex;gap:10px;flex-wrap:wrap;
  justify-content:center}
.ol-empty-inline{padding:34px 24px}
.ol-catcallout{margin-top:40px}
.ol-catcallout p{margin-top:9px;font-size:13.5px;color:var(--granite);max-width:640px;
  line-height:1.7}
.ol-catcallout-act{margin-top:16px;display:flex;gap:10px;flex-wrap:wrap}

@media (max-width:900px){
  .ol-fx{max-height:none;overflow:visible}
  .ol-fx-toggle{display:flex}
  html.ol-js .ol-fx:not(.ol-fx-open) .ol-fx-body{display:none}
  .ol-catlayout{padding-top:20px;gap:20px}
  .ol-pag-of{margin-left:0;width:100%;order:2}
}

@media (max-width:600px){
  .ol-tbar{align-items:flex-start;flex-direction:column;gap:12px}
  .ol-sortform{width:100%}
  .ol-sortform .ol-sortsel{flex:1}
  .ol-catlogo img{height:30px}
}

/* ==========================================================================
   21. THE PRODUCT PAGE  (Phase 4, WordPress build)

   Section 14 already carries the whole PDP shell, transformed from the
   prototype: .ol-pdp, .ol-gal, .ol-thumbs, .ol-th, .ol-mainshot, .ol-code,
   .ol-zoom, .ol-pbox, .ol-fitpanel, .ol-sstrip, .ol-tabs, .ol-prose,
   .ol-tabpane. None of it is touched here.

   Two things this section is for. First, the prototype's gallery held inline
   SVG glyphs and this one holds photographs, so the image cases have no rules
   at all in section 14 -- `.ol-th svg` and `.ol-mainshot>svg` are the only
   media rules there. Second, and this is most of the file, the add-to-cart
   form is WooCommerce's own markup rather than ours: form.cart, .quantity,
   .variations, .single_add_to_cart_button, .woocommerce-variation. The
   stylesheet had exactly zero rules matching any of those, so unstyled they
   render as a bare browser table with a grey submit button in the middle of
   an otherwise finished page.

   Hand-rolling that form instead was the alternative, and it was rejected:
   80 products are variable with 869 variations between them, one of them has
   32, and a hand-rolled variation resolver that picks the wrong one puts the
   wrong part in somebody's cart. Restyling is the cheaper mistake.
   ========================================================================== */

/* ---- gallery: the photograph cases ---- */

/* width/height 100% with object-fit, NOT max-width/max-height:auto.
   .ol-th sizes itself with aspect-ratio:1 and no explicit height, so its height
   is indefinite as far as percentage resolution is concerned -- which makes
   `max-height:100%` compute to none, and a portrait thumbnail then rendered 88px
   tall inside a 60px tile and was clipped by the tile's overflow:hidden. It read
   as a blank cream square, which is a confusing way to fail: the file had
   downloaded, the pixels were there (measured: 98-100% non-white), and nothing
   showed in the console. Giving the image a definite box and letting object-fit
   letterbox inside it does not depend on that resolution at all. */
.ol-th img{width:100%;height:auto;aspect-ratio:1;object-fit:contain;display:block}
.ol-mainshot img{width:100%;height:100%;object-fit:contain;padding:26px;display:block}

/* The main shot is a button in all but name once the lightbox exists, so it
   says so on hover rather than only through the corner label. */
.ol-mainshot img{cursor:zoom-in;transition:transform .5s var(--ease)}
.ol-mainshot:hover img{transform:scale(1.03)}
.ol-mainshot .ol-zoom{cursor:pointer;z-index:1}
.ol-mainshot .ol-zoom:hover{border-color:var(--navy);color:var(--navy)}

/* No thumbs to show: the 80px rail would otherwise stay as an empty column and
   push the shot off-centre. 204 of 399 products have no gallery. */
.ol-gal-solo{grid-template-columns:1fr}

/* The eight products with no image at all. Same glyph the card falls back to. */
.ol-shot-ph{color:var(--dust);opacity:.55}

/* ---- the buy column ---- */
.ol-pdp-eyebrow{font-size:10.5px}
.ol-pdp-eyebrow a{color:inherit;text-decoration:none;border-bottom:1px solid transparent}
.ol-pdp-eyebrow a:hover{border-bottom-color:currentColor}

.ol-pdp .ol-sub p:last-child{margin-bottom:0}

/* The price row: price left, availability right, on one baseline. .ol-big holds
   get_price_html(), which on a variable product is a RANGE -- "R200 to R300" --
   so it has to be allowed to wrap rather than sized for one figure. */
.ol-pbox .ol-big{font-size:clamp(24px,3.2vw,34px);line-height:1.1}
.ol-pbox .ol-big del{font-size:.55em;font-weight:600;color:var(--dust);
  margin-right:8px;text-decoration-thickness:1px}
.ol-pbox .ol-big ins{text-decoration:none}
.ol-pbox .ol-big .woocommerce-Price-currencySymbol{font-size:.62em;font-weight:600;
  vertical-align:.18em;margin-right:1px}
/* On a variable product WooCommerce prints the range twice: once as
   "R200 to R300" and again as a screen-reader sentence, "Price range: R200
   through R300". Both are wanted and only one is meant to be seen -- and no
   rule is needed here, because section 2 already hides .screen-reader-text
   globally with !important. Worth the note: it looked like a bug in the price
   markup until I checked which stylesheet was already handling it. */
.ol-pbox-note{margin-top:8px;color:var(--dust)}
.ol-pbox-stock{margin-left:auto;text-align:right}
.ol-stk{font-weight:700}
.ol-stk-instock{color:var(--fit)}
.ol-stk-onbackorder{color:#996800}
.ol-stk-outofstock{color:var(--granite)}

.ol-pbox-alt{margin-top:12px}
.ol-pbox-oos{margin-top:4px}

/* ---- WooCommerce's add-to-cart form ---- */
.ol-pbox form.cart{margin:0}
.ol-pbox form.cart::after{content:"";display:table;clear:both}

/* The quantity field. WooCommerce ships a bare number input; this gives it the
   pill and the 1.5px hairline every other control on the site has. The spinner
   arrows stay -- they are the platform's own increment control and replacing
   them with two buttons, as the prototype did, means reimplementing min, max,
   step and the keyboard behaviour that already works. */
.ol-pbox .quantity{display:inline-flex;align-items:center;border:1.5px solid var(--hair);
  border-radius:var(--r3);background:#fff;overflow:hidden;flex-shrink:0}
.ol-pbox .quantity input.qty{width:76px;border:0;background:none;text-align:center;
  padding:14px 6px 14px 12px;font-family:var(--body);font-size:15px;font-weight:700;
  color:var(--navy);appearance:auto}
.ol-pbox .quantity input.qty:focus{outline:none}
.ol-pbox .quantity:focus-within{border-color:var(--navy)}

/* The add-to-cart button.

   Every metric here is copied from .ol-btn and .ol-btn-red rather than chosen,
   including the sheen sweep on hover. This is the primary CTA on the most
   visited template on the site, and a primary CTA that is two pixels shorter
   and a different weight from every other one is precisely the detail that
   makes a page read as assembled instead of built. The alternative was to
   override WooCommerce's two add-to-cart templates so the markup could carry
   .ol-btn directly -- rejected for the reason in this section's header, since
   those same templates carry the variation resolution.

   The selector is long on purpose. WooCommerce ships
     .woocommerce button.button.alt{background-color:#7f54b3}
   at 0-3-1, and this button carries `alt`, so my first attempt at 0-3-0 lost
   to it and the primary CTA rendered in WooCommerce's brand purple at 50%
   opacity -- a pale lavender pill, which is both off-palette and the exact
   thing the design's anti-slop check flags. Measured, not guessed: the
   computed background was rgb(127,84,179). .ol-site on the body plus an
   element qualifier puts this at 0-4-1, which wins outright rather than
   depending on which stylesheet loads last. */
.ol-site .ol-pbox button.single_add_to_cart_button.button{flex:1;min-width:180px;height:48px;opacity:1;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  background:var(--red);color:#fff;border:1.5px solid transparent;
  border-radius:var(--r3);padding:15px 28px;
  font-family:var(--body);font-size:13.5px;font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;cursor:pointer;text-align:center;
  position:relative;overflow:hidden;transition:.28s var(--ease);box-shadow:none}
.ol-site .ol-pbox button.single_add_to_cart_button.button:hover{background:var(--redhover);
  transform:translateY(-2px);box-shadow:0 14px 28px -12px rgba(255,31,42,.55)}
.ol-site .ol-pbox button.single_add_to_cart_button.button:after{content:"";position:absolute;
  top:0;left:-60%;width:40%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.3),transparent);
  transform:skewX(-20deg)}
.ol-site .ol-pbox button.single_add_to_cart_button.button:hover:after{animation:sheen .8s var(--ease)}
.ol-site .ol-pbox button.single_add_to_cart_button.button:focus-visible{outline:2px solid var(--navy);
  outline-offset:3px}

/* Variation not chosen yet. WooCommerce adds .disabled and
   .wc-variation-selection-needed and then intercepts the click to explain
   why, so the button must LOOK unavailable without being pointer-events:none
   -- killing the click would kill the explanation with it. */
/* Not opacity. Dropping a red button to 45% over a white card produces a pale
   pink-lavender that belongs to no part of this palette and reads as a third
   brand colour rather than as an unavailable control. It was the first thing
   visibly wrong in the rendered page, and it is on the most-seen state of the
   most-seen button: a variable product shows it until an option is chosen.
   A solid bone fill with dust text says "not yet" in colours the site owns.

   Still not pointer-events:none. WooCommerce intercepts the click on this
   button to say which option is missing, and disabling the click would take
   the explanation with it. */
.ol-site .ol-pbox button.single_add_to_cart_button.disabled,
.ol-site .ol-pbox button.single_add_to_cart_button.wc-variation-selection-needed{
  background:var(--bone3);color:var(--dust);border-color:var(--hair);
  box-shadow:none;cursor:not-allowed;opacity:1}
.ol-site .ol-pbox button.single_add_to_cart_button.disabled:after,
.ol-site .ol-pbox button.single_add_to_cart_button.wc-variation-selection-needed:after{display:none}
.ol-site .ol-pbox button.single_add_to_cart_button.disabled:hover,
.ol-site .ol-pbox button.single_add_to_cart_button.wc-variation-selection-needed:hover{
  transform:none;background:var(--bone3);color:var(--dust);box-shadow:none}

/* The simple-product row: quantity beside the button. */
.ol-pbox form.cart:not(.variations_form){display:flex;gap:11px;align-items:stretch;
  flex-wrap:wrap}
.ol-pbox .woocommerce-variation-add-to-cart{display:flex;gap:11px;align-items:stretch;
  flex-wrap:wrap;margin-top:16px}

/* ---- the variation selects ----
   WooCommerce renders these as a table. Turned into a stack, because a two
   column table of label and select inside a 26px-padded box gives the select
   about 180px, and "Comfort | Medium | Heavy | Extra Heavy" does not fit in it. */
.ol-pbox table.variations{width:100%;border-collapse:collapse;margin:0 0 4px;
  display:block}
.ol-pbox table.variations tbody,
.ol-pbox table.variations tr{display:block}
.ol-pbox table.variations th,
.ol-pbox table.variations td{display:block;padding:0;text-align:left;border:0}
.ol-pbox table.variations tr+tr{margin-top:14px}
.ol-pbox table.variations th.label label{font-family:var(--mono);font-size:11.5px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--navy);font-weight:700;
  display:block;margin-bottom:8px}
.ol-pbox td.value{position:relative}

/* The select gets the same pill and the same chevron as the sort control. The
   chevron is set with longhands, not the `background` shorthand: section 15's
   `.ol-field select` uses the shorthand and wiped the province select's arrow
   in the centre lookup, which took a while to find. Not repeating it. */
.ol-pbox td.value select{width:100%;appearance:none;-webkit-appearance:none;
  border:1.5px solid var(--hair);border-radius:var(--r3);
  padding:13px 40px 13px 18px;font-family:var(--body);font-size:14.5px;font-weight:600;
  color:var(--navy);cursor:pointer;
  background-color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23002D52' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 16px center}
.ol-pbox td.value select:focus{outline:none;border-color:var(--navy)}

.ol-pbox a.reset_variations{display:inline-block;margin-top:9px;font-family:var(--mono);
  font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--red);
  text-decoration:underline;text-underline-offset:3px}
/* WooCommerce shows this only once a variation is chosen, by inline style. A
   `display:inline-block` here would override that and print a Clear link with
   nothing to clear, so visibility is left to the script. */

/* ---- the chosen variation's own price and stock ---- */
.ol-pbox .woocommerce-variation{margin-top:16px}
.ol-pbox .woocommerce-variation-price{font-weight:800;font-size:22px;color:var(--navy);
  letter-spacing:-.02em}
.ol-pbox .woocommerce-variation-price .woocommerce-Price-currencySymbol{font-size:.66em;
  font-weight:600;vertical-align:.16em}
.ol-pbox .woocommerce-variation-price del{font-size:.6em;color:var(--dust);
  font-weight:600;margin-right:7px}
.ol-pbox .woocommerce-variation-price ins{text-decoration:none}
.ol-pbox .woocommerce-variation-availability p.stock{margin-top:6px;font-family:var(--mono);
  font-size:11px;letter-spacing:.07em;text-transform:uppercase;font-weight:700}
.ol-pbox .woocommerce-variation-availability p.in-stock{color:var(--fit)}
.ol-pbox .woocommerce-variation-availability p.available-on-backorder{color:#996800}
.ol-pbox .woocommerce-variation-availability p.out-of-stock{color:var(--red)}
.ol-pbox .woocommerce-variation-description{margin-top:10px;font-size:13.5px;
  color:var(--granite);line-height:1.65}
.ol-pbox .woocommerce-variation-description p:last-child{margin-bottom:0}

/* ---- the fitment panel set ----
   A wrapper only. Every state is rendered by PHP and all but one carries the
   hidden attribute, so the panel a shopper sees with the script blocked is the
   one that claims least. */
.ol-fitset .ol-fitpanel p:last-child{margin-bottom:0}
.ol-fitpanel .ol-t b{font-weight:800}
.ol-fitpanel .ol-chg{text-decoration:none;background:none;border-width:0 0 1px 0;
  border-style:solid;padding:0}
.ol-fitpanel .ol-chg:hover{color:var(--red);border-bottom-color:var(--red)}

/* ---- the lower content ---- */
.ol-pdp-lower{padding-bottom:56px}
.ol-pdp-h{font-family:var(--body);font-style:normal;font-size:19px;font-weight:800;
  text-transform:none;color:var(--navy);margin-bottom:16px;letter-spacing:0}
/* With one pane there is no tab strip, so the pane is not a tabpanel and must
   not inherit the display:none that .ol-tabpane starts from. */
.ol-panes>.ol-tabpane.ol-on{display:block}
.ol-prose table td:first-child{width:230px}
.ol-prose img{max-width:100%;height:auto;border-radius:var(--r2)}
.ol-prose h2,.ol-prose h3{font-family:var(--body);font-style:normal;font-weight:800;
  color:var(--navy);font-size:17px;text-transform:none;margin:26px 0 10px;letter-spacing:0}
.ol-prose ol{margin:0 0 16px 18px;color:var(--granite);font-size:14px;line-height:1.85}
.ol-prose strong{color:var(--navy)}
.ol-prose>*:first-child{margin-top:0}

.ol-pdp-relh{font-size:30px}

/* ---- the lightbox ----
   Replaces photoswipe, which came with Hello Elementor's WooCommerce gallery
   support and is dropped in inc/product.php. Navy at 92% rather than black:
   pure black is not in the palette and a black scrim behind a navy site reads
   as a different application taking over. */
.ol-lb{position:fixed;inset:0;z-index:9999;background:rgba(0,29,54,.92);
  display:grid;place-items:center;padding:44px 28px;cursor:zoom-out}
.ol-lb img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  border-radius:var(--r2);background:#fff;cursor:default}
.ol-lb-x{position:absolute;top:18px;right:22px;width:44px;height:44px;border:0;
  border-radius:var(--r3);background:rgba(255,255,255,.14);color:#fff;padding:0;
  display:grid;place-items:center;cursor:pointer;transition:.2s var(--ease)}
.ol-lb-x:hover{background:#fff;color:var(--navy)}
.ol-lb-x:focus-visible{outline:2px solid #fff;outline-offset:3px}

/* ---- the fitment bar's empty state ----
   Was an inline style inside the widget. Moved out when the bar became a
   function two templates also call, so the one markup has the one rule. */
.ol-fitpill-none{font-size:14px;opacity:.8}

@media (max-width:1024px){
  .ol-pdp{grid-template-columns:1fr;gap:34px}
  .ol-pdp-relh{font-size:24px}
  /* The title had no step at all: 36px at every width, which on a phone
     turns a supplier-length part name into six lines above the price. */
  .ol-pdp h1{font-size:30px}
}

@media (max-width:600px){
  /* Tracking eases off with the size: -.03em is drawn for 36px and pinches
     uppercase italic shut once the size comes down. */
  .ol-pdp h1{font-size:26px;letter-spacing:-.02em}
  /* The thumb rail goes horizontal under the shot: a vertical column of five
     80px thumbs is 450px of screen before the price. */
  .ol-gal{grid-template-columns:1fr}
  .ol-thumbs{flex-direction:row;overflow-x:auto;padding-bottom:4px;order:2;
    scrollbar-width:none}
  .ol-thumbs::-webkit-scrollbar{display:none}
  .ol-thumbs .ol-th{width:64px;flex-shrink:0}
  .ol-mainshot{order:1}
  .ol-mainshot img{padding:14px}
  .ol-pbox{padding:20px 18px}
  .ol-pbox-stock{margin-left:0;text-align:left}
  .ol-site .ol-pbox button.single_add_to_cart_button.button{min-width:0;width:100%}
  .ol-pbox form.cart:not(.variations_form),
  .ol-pbox .woocommerce-variation-add-to-cart{flex-direction:column}
  .ol-pbox .quantity{align-self:flex-start}
  .ol-prose table td:first-child{width:auto;display:block;padding-bottom:0;border:0}
  .ol-prose table td:last-child{display:block;padding-top:4px}
}

/* ==========================================================================
   22. LEGAL / POLICY PAGES  (Phase 5, WordPress build)

   Privacy, Terms, PAIA, Refunds. Almost all of this rides on .ol-prose from
   section 14 and the h2/h3/ol rules section 21 added, so what follows is only
   the document furniture: a reading measure, the date line, and the contact
   block at the end of a policy.

   The prototype has no page for any of this. That is not an oversight in the
   prototype -- a legal page is a document, and designing one is mostly
   deciding to leave it alone.
   ========================================================================== */

.ol-legal{padding:34px 0 80px}

/* 68 characters, near enough. .ol-prose caps at 740px, which is right for a
   product description sitting beside a photograph and slightly wide for nine
   sections of continuous prose with nothing to break the line up. */
.ol-legal-body{max-width:720px}

.ol-legal-meta{font-family:var(--mono);font-size:11px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--dust);margin:0 0 26px}

/* The numbered headings. A policy is referred to by section number in
   correspondence -- "as set out in clause 4" -- so the numbers in the copy are
   load-bearing and get a rule above them that makes each section findable when
   somebody is scanning for one, rather than being swallowed into the run of
   text. */
.ol-legal-body h2{font-family:var(--body);font-style:normal;font-weight:800;
  font-size:19px;color:var(--navy);text-transform:none;letter-spacing:0;
  margin:38px 0 12px;padding-top:22px;border-top:1px solid var(--hair2)}
.ol-legal-body>*:first-child,
.ol-legal-body h2:first-child{margin-top:0;padding-top:0;border-top:0}

.ol-legal-body p{font-size:15px;line-height:1.8}
.ol-legal-body ul{margin:0 0 18px 20px;font-size:15px;line-height:1.8}
.ol-legal-body li{margin-bottom:7px}
.ol-legal-body li strong{color:var(--navy)}

/* Contact details at the foot of a policy: this is the one block on the page
   somebody is looking for rather than reading, so it gets the bone panel and
   the red rule that mark a callout everywhere else on the site. */
.ol-legal-contact{background:var(--bone);border-radius:var(--r);
  border-left:4px solid var(--red);padding:24px 28px;margin-top:34px}
.ol-legal-contact p{margin-bottom:6px}
.ol-legal-contact p:last-child{margin-bottom:0}
.ol-legal-contact strong{display:block;color:var(--navy);font-size:15px;
  margin-bottom:8px}
.ol-legal-contact a{color:var(--navy);border-bottom:1px solid var(--hair);
  text-decoration:none}
.ol-legal-contact a:hover{color:var(--red);border-bottom-color:var(--red)}

/* The footer's legal line, now that it is links rather than inert text. */
.ol-ftr-legal a{color:inherit;text-decoration:none;border-bottom:1px solid transparent}
.ol-ftr-legal a:hover{color:#fff;border-bottom-color:rgba(255,255,255,.45)}

@media (max-width:600px){
  .ol-legal{padding:24px 0 56px}
  .ol-legal-body h2{font-size:17px;margin-top:30px}
  .ol-legal-contact{padding:20px 18px}
}

/* ---- 22b. THE SECTION INDEX ----
   Added after the policy went live, because a 720px measure inside a 1440px
   container leaves most of a desktop screen empty beside it and a nine-section
   reference document has an obvious use for that space.

   The grid places both children explicitly rather than relying on source order.
   The index is FIRST in the markup -- a contents list belongs before the
   contents for a screen reader and for a browser with no stylesheet -- and
   second visually, which is where it belongs beside a reading column that
   starts at the container's left gutter. */
/* Capped as a pair rather than stretched across the container. Left to fill
   a 1440px container, the 720px measure and the 232px index end up at opposite
   edges of the screen with 380px of nothing between them -- two things on a
   page rather than a document with its own contents list beside it. 1040px
   holds them together, and the body's own max-width comes off because the
   column now governs the measure. */
.ol-legal-wrap{display:grid;grid-template-columns:minmax(0,1fr) 232px;gap:48px;
  align-items:start;max-width:1040px}
.ol-legal-wrap>.ol-legal-body{max-width:none}
.ol-legal-wrap>.ol-legal-body{grid-column:1;grid-row:1}
.ol-legal-wrap>.ol-legal-toc{grid-column:2;grid-row:1}

/* Sticky, and offset by the header's height plus a little air. Capped and
   scrollable for the same reason the facet rail is: a Terms document with
   thirty clauses would otherwise run past the bottom of the viewport with no
   way to reach the end of it. */
.ol-legal-toc{position:sticky;top:120px;max-height:calc(100vh - 150px);
  overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;
  scrollbar-color:var(--hair) transparent}
.ol-legal-toc-in{border-left:2px solid var(--hair);padding-left:20px}

.ol-legal-toc-h{font-family:var(--mono);font-size:10.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dust);font-weight:700;margin:0 0 14px;
  border:0;padding:0}

/* The document's own numbering, restored by a counter. The link text has the
   number stripped from it, so a heading that already reads "4." does not end up
   as "4. 4. How We Share Your Information" in the index -- and a policy whose
   headings carry no numbers still gets them here, which is what somebody
   quoting "clause 4" back to you needs. */
.ol-legal-toc ol{list-style:none;counter-reset:ol-toc;margin:0;padding:0}
.ol-legal-toc li{counter-increment:ol-toc;margin-bottom:11px;line-height:1.45}
.ol-legal-toc a{display:flex;gap:9px;font-size:13px;color:var(--granite);
  text-decoration:none;transition:.2s var(--ease)}
.ol-legal-toc a:before{content:counter(ol-toc) ".";font-family:var(--mono);
  font-size:11px;color:var(--dust);flex-shrink:0;padding-top:1px}
.ol-legal-toc a:hover{color:var(--red)}
.ol-legal-toc a:hover:before{color:var(--red)}
.ol-legal-toc a:focus-visible{outline:2px solid var(--navy);outline-offset:3px;
  border-radius:3px}

/* A jump has to land with the heading visible, not tucked under the header that
   is pinned over it. */
.ol-legal-body h2{scroll-margin-top:118px}

@media (max-width:980px){
  /* One column, and the index goes back to being what it is in the source: a
     contents list at the top of the document. Not hidden -- on a phone, where
     the whole policy is one long scroll, it is more useful than on a desktop,
     not less. */
  .ol-legal-wrap{grid-template-columns:1fr;gap:26px}
  .ol-legal-wrap>.ol-legal-toc{grid-column:1;grid-row:1}
  .ol-legal-wrap>.ol-legal-body{grid-column:1;grid-row:2}
  .ol-legal-toc{position:static;max-height:none;overflow:visible}
  .ol-legal-toc-in{border-left:0;padding:18px 20px;background:var(--bone);
    border-radius:var(--r)}
  .ol-legal-toc ol{columns:2;column-gap:26px}
  .ol-legal-toc li{break-inside:avoid}
}

@media (max-width:600px){
  .ol-legal-toc ol{columns:1}
}

/* ==========================================================================
   21e. ENQUIRY-ONLY PARTS
   The variation dropdowns stay. They are how an enquiry learns which of twelve
   variants the shopper meant, and losing them would leave somebody typing "the
   2.8 diesel one, I think" into a message box.

   What goes is the furniture that cannot work: the quantity box and the
   add-to-cart button. Note what this is NOT doing -- it is not what stops the
   sale. is_purchasable in inc/enquiry.php does that, everywhere WooCommerce
   asks, including the Store API and a hand-typed ?add-to-cart= URL. If every
   rule below failed to load, the page would look untidy and the part still
   could not be bought. The original relied on display:none and a stack of
   !important for the whole job, which stopped nobody.
   ========================================================================== */
.ol-enquiry-only .ol-pbox .quantity,
.ol-enquiry-only .ol-pbox .woocommerce-variation-add-to-cart,
.ol-enquiry-only .ol-pbox button.single_add_to_cart_button{display:none}
.ol-enquiry-only .ol-pbox .ol-enquire{margin-top:16px}

/* ==========================================================================
   21f. A VARIATION THAT CANNOT BE BOUGHT
   Printed hidden by inc/product.php and swapped in by pdpUnavailable() when the
   chosen variation is out of stock with no backorder. 21 variable products in
   this catalogue have at least one variation in that state, and every one of
   them currently ends at a greyed button.
   ========================================================================== */
.ol-hide{display:none!important}
.ol-pbox-unavail[hidden]{display:none}
.ol-pbox-unavail{display:grid;gap:12px;margin-top:4px}
.ol-pbox-unavail-note{color:var(--red)}

/* ==========================================================================
   21g. THE ENQUIRY POPUP

   Elementor renders the form; this puts it on the site's own controls.

   The form rules moved off .elementor-2365 and onto .ol-form on 28 Sep,
   when the quote page needed the same treatment. Still not .elementor-form:
   a form only gets this by having ol-form typed into its CSS Classes box in
   Elementor, so it is opt-in rather than something that reaches every form
   the team ever builds. Only the popup heading below is still id-scoped,
   because that is the popup's own title and not part of the form.

   Anything the team sets in Elementor itself arrives as inline style and wins
   over this, which is the right way round: these are defaults that stop the
   popup looking like a different website, not a cage.
   ========================================================================== */
.elementor-2365 .elementor-heading-title{font-size:22px;letter-spacing:-.01em;
  text-transform:none;font-style:normal;font-weight:800;color:var(--navy);
  margin-bottom:6px}

.ol-form .elementor-field-label{font-family:var(--mono);font-size:10.5px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--dust);font-weight:700;
  margin-bottom:6px}

.ol-form .elementor-field-group .elementor-field{border:1px solid var(--hair);
  border-radius:var(--r3);padding:13px 18px;font-family:var(--body);font-size:14px;
  background:#fff;color:var(--graphite);transition:.2s var(--ease);box-shadow:none;
  min-height:0}
.ol-form .elementor-field-group textarea.elementor-field{border-radius:var(--r);
  min-height:92px;resize:vertical}
.ol-form .elementor-field-group .elementor-field:focus{border-color:var(--navy);
  box-shadow:0 0 0 3px rgba(0,45,82,.08);outline:0}

.ol-form .elementor-button[type=submit]{background:var(--red);color:#fff;
  border:0;border-radius:var(--r3);font-family:var(--body);font-weight:800;
  font-size:13.5px;letter-spacing:.02em;text-transform:uppercase;
  padding:15px 28px;transition:.22s var(--ease)}
.ol-form .elementor-button[type=submit]:hover{background:var(--redhover)}

/* The two messages a shopper only ever sees once, and only at the moment they
   matter most -- so they get the same callout treatment as the rest of the
   site rather than Elementor's default green and red bars. */
.ol-form .elementor-message{font-family:var(--body);font-size:13.5px;
  border-radius:var(--r);padding:12px 16px;margin-top:12px}
.ol-form .elementor-message-success{background:rgba(15,123,62,.06);
  color:var(--fit);border:1px solid rgba(15,123,62,.25)}
.ol-form .elementor-message-danger{background:rgba(255,31,42,.05);
  color:var(--red);border:1px solid rgba(255,31,42,.25)}


/* ---------------------------------------------------------------------------
   24. THE BARE SEARCH URL  (Phase 6, WordPress build)

   search.php answers /?s=term when nothing scoped it to products -- a pasted
   link, a bookmark, a browser search bar. Everything a customer can submit
   from the site carries post_type=product and lands on the catalogue archive
   instead, so this is a small page by design and it borrows almost all of its
   parts: the same header band, the same cards, the same pagination, the same
   empty state. What is new is only the two pieces the archive has no use for
   -- the line that hands off to the faceted version, and the list of matches
   that are not parts.

   That second list is deliberately not a card. A card on this site promises a
   price, a part code and a fitment state; a policy page has none of the three,
   and dropping one into the grid would be the layout telling a lie the copy
   then has to walk back. It gets a quieter row with its post type named on it.
   --------------------------------------------------------------------------- */

/* NOT the header search pill. This is the wrapper around the search
   results page. It was called .ol-srch too, and being later in the file it
   was overriding the header component site-wide -- which is why the header
   magnifier sat hard against the left edge with no padding. */
.ol-srchpage{padding:0 0 8px}

/* The hand-off. Bone rather than white so it reads as a note about the page
   rather than the first result on it. */
.ol-srch-refine{display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  background:var(--bone);border:1px solid var(--hair);border-radius:var(--r2);
  padding:14px 18px;margin:0 0 26px}
.ol-srch-refine p{flex:1 1 300px;margin:0;font-family:var(--body);
  font-size:14px;line-height:1.5;color:var(--granite)}
.ol-srch-refine .ol-btn{flex:0 0 auto}

/* The non-product matches. The rule above them is the whole separation: one
   hairline says the grid has ended and a different kind of thing follows. */
.ol-srch-more{margin:44px 0 0;padding-top:32px;border-top:1px solid var(--hair)}
.ol-srch-list{list-style:none;margin:16px 0 0;padding:0;display:grid;gap:10px}
.ol-srch-item a{display:block;text-decoration:none;background:#fff;
  border:1px solid var(--hair);border-radius:var(--r2);padding:16px 20px;
  transition:border-color .22s var(--ease),box-shadow .22s var(--ease),transform .22s var(--ease)}
.ol-srch-item a:hover{border-color:var(--navy);box-shadow:var(--e1);transform:translateY(-1px)}
.ol-srch-item a:focus-visible{outline:2px solid var(--navy);outline-offset:2px}
.ol-srch-kind{display:block;font-family:var(--mono);font-size:9.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--dust);margin-bottom:7px}
.ol-srch-t{font-family:var(--body);font-weight:800;font-size:16px;
  line-height:1.3;color:var(--navy);margin:0}
.ol-srch-item p{margin:7px 0 0;font-family:var(--body);font-size:13.5px;
  line-height:1.55;color:var(--granite)}

/* /?s= with nothing after it. Answered with the question rather than with the
   entire catalogue sorted by date, which is what the default loop would do. */
.ol-srch-blank{padding:72px 0 56px;text-align:center}
.ol-srch-blank .ol-h-sec{margin:10px 0 12px}
.ol-srch-blank p{max-width:52ch;margin:0 auto 24px;font-family:var(--body);
  font-size:15px;line-height:1.6;color:var(--granite)}
.ol-srch-blank .ol-empty-act{justify-content:center}

/* Two across once there is room. Kept local to this section rather than added
   to 18, so the whole search fallback stays readable in one place. */
@media (min-width:900px){
  .ol-srch-list{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:600px){
  .ol-srch-refine{gap:12px;padding:13px 15px}
  .ol-srch-refine .ol-btn{width:100%;text-align:center}
  .ol-srch-blank{padding:48px 0 40px}
}

/* 21h. THE NEW CHIP ON A PRODUCT PAGE

   Same word, same navy and same mono face as the card tag, so a shopper who
   followed the badge from a grid meets the same object on arrival rather than
   a second thing that happens to say New. It sits inline at the head of the
   brand and category eyebrow, so it takes that row height and needs no space
   of its own. */
.ol-pdp-new{display:inline-block;vertical-align:baseline;margin-right:10px;
  background:var(--navy);color:#fff;font-family:var(--mono);font-size:10px;
  font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  padding:3px 9px;border-radius:var(--r3)}

/* ==========================================================================
   26. CLASSIC WOOCOMMERCE NOTICES
   ==========================================================================
   The last surface still wearing WooCommerce own look: the line that appears
   when something goes into the basket, when a variation has not been chosen,
   or when a coupon is refused. woocommerce_output_all_notices() prints them
   into a bare wrapper that sits OUTSIDE .ol-container, so as well as being
   green they ran edge to edge on a page whose every other element stops at
   1440px. This gives the wrapper the same gutter as everything else.

   The basket and the checkout do not come through here: those are blocks and
   their notices are skinned in ol-checkout.css. The account pages carry their
   own copy under #ol-acc, which outranks all of this. What is left is the
   product page, the shop, search and the category archives, which is where a
   shopper actually meets one.
   ========================================================================== */
.woocommerce-notices-wrapper:empty{display:none}
.woocommerce-notices-wrapper{max-width:1440px;margin:0 auto;padding:24px 40px 0}

.woocommerce-notices-wrapper .woocommerce-message,
.woocommerce-notices-wrapper .woocommerce-info,
.woocommerce-notices-wrapper .woocommerce-error{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  background:var(--bone);border:1px solid var(--hair);border-left:3px solid var(--navy);
  border-radius:var(--r2);padding:16px 20px;margin:0 0 14px;list-style:none;
  font-family:var(--body);font-size:14px;line-height:1.6;color:var(--navy)}
.woocommerce-notices-wrapper .woocommerce-error{border-left-color:var(--red);color:var(--red)}

/* WooCommerce draws a tick, an i and a cross in its own icon font, which this
   theme does not load: left alone they render as an empty box down the left of
   every notice. Removed rather than replaced, because the colour of the left
   edge already says which of the three this is. */
.woocommerce-notices-wrapper .woocommerce-message::before,
.woocommerce-notices-wrapper .woocommerce-info::before,
.woocommerce-notices-wrapper .woocommerce-error::before{content:none}

/* The error notice is a <ul> and each sentence in it is an <li>. */
.woocommerce-notices-wrapper ul.woocommerce-error{display:block}
.woocommerce-notices-wrapper ul.woocommerce-error li{margin:0;padding:0;list-style:none}
.woocommerce-notices-wrapper ul.woocommerce-error li+li{margin-top:6px}

/* Where the View basket link sits in the notice depends on which path put it
   there: the add-to-basket message writes it after the sentence, and several
   other callers write it before. Both were seen on this build. order:1 pins it
   last whichever way it arrives.

   It has to be done by pushing the button rather than pulling the text: the
   sentence is a bare text node, which makes it an anonymous flex item, and an
   anonymous flex item cannot take an order of its own. Same trap as the
   account notices. */
.woocommerce-notices-wrapper .woocommerce-message .button,
.woocommerce-notices-wrapper .woocommerce-info .button{order:1;margin-left:auto}

.woocommerce-notices-wrapper .button{
  display:inline-block;background:var(--navy);color:#fff;border:0;border-radius:var(--r3);
  font-family:var(--body);font-size:12px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;text-decoration:none;padding:10px 18px;white-space:nowrap;
  transition:background .18s ease}
.woocommerce-notices-wrapper .button:hover,
.woocommerce-notices-wrapper .button:focus{background:var(--redhover);color:#fff;text-decoration:none}

/* Hello Elementor underlines every link inside .page-content. */
.woocommerce-notices-wrapper a:not(.button){color:var(--navy);font-weight:700}

@media(max-width:980px){
  .woocommerce-notices-wrapper{padding:18px 22px 0}
  .woocommerce-notices-wrapper .woocommerce-message .button,
  .woocommerce-notices-wrapper .woocommerce-info .button{margin-left:0;width:100%;text-align:center}
}


/* ==========================================================================
   27. ADDING TO THE BASKET FROM A CARD
   ==========================================================================
   The shop used to send the shopper to the basket page on every add, which on
   a parts catalogue meant somebody buying a five-piece kit was thrown back to
   the grid five times. That setting is off, so the add happens in place -- and
   the feedback has to happen in place with it.

   WooCommerce draws its own: a spinner and a tick in an icon font this theme
   does not load, plus a View basket link appended after the button. In the
   price row that link wrapped and pushed the card taller than the ones beside
   it. All three are suppressed here and markAdded() in ol-app.js turns the
   button itself into a tick for two seconds instead.
   ========================================================================== */
.ol-pfoot a.added_to_cart{display:none}
.ol-add.loading::after,.ol-add.added::after{content:none}
.ol-add.loading{opacity:.55;pointer-events:none}
.ol-add.ol-done .ol-i{stroke:currentColor}


/* ==========================================================================
   28. HERO HEIGHT ON SMALL SCREENS
   ==========================================================================
   80vh is a good desktop proportion and a bad phone one. A phone in portrait
   spends 80vh on a photograph and pushes the search field, the quick links and
   the fitment bar below the fold -- and on iOS the toolbar makes vh taller than
   the visible area, so it is worse than the number suggests. Below 640px the
   band goes back to being sized by its own padding.
   ========================================================================== */
@media(max-width:640px){
  .ol-heroband{min-height:auto;display:block}
}


/* ==========================================================================
   29. CATEGORY TILE TONES  (client, 22 Sep)
   ==========================================================================
   The grid keeps the layout it had -- name, count, four child links and the
   All N link -- and takes the colour and the icon weight from the build tiles.
   Eight white cards in a row read as a table of contents; the tones make it
   read as a shelf, which is what it is.

   Everything below is a tone class on the tile. Nothing here changes the
   structure, so the widget controls that set the column count and the number
   of child links still do exactly what they did.
   ========================================================================== */
.ol-cat{border-color:transparent}

/* The icon was sized to sit under the text at 8% grey. On a navy tile that
   disappears, and the build tiles carry it as a real element rather than a
   watermark, so it grows and the opacity is set per tone below. */
.ol-cat-g{width:136px;right:-18px;bottom:-16px}

/* ---- dark tones: navy and blue ---- */
.ol-cat--deep{background:var(--deep)}
.ol-cat--blue{background:var(--mid)}
.ol-cat--deep .ol-cat-n,.ol-cat--blue .ol-cat-n{color:#fff}
.ol-cat--deep .ol-cat-c,.ol-cat--blue .ol-cat-c{color:rgba(255,255,255,.52)}
.ol-cat--deep .ol-cat-s a,.ol-cat--blue .ol-cat-s a{color:rgba(255,255,255,.74)}
.ol-cat--deep .ol-cat-s a:hover,.ol-cat--blue .ol-cat-s a:hover{color:#fff}
.ol-cat--deep .ol-cat-g,.ol-cat--blue .ol-cat-g{color:#fff;opacity:.13}

/* Red on navy is the brand pairing and clears AA at this weight and size;
   on the mid blue it does not, so that tile takes white. */
.ol-cat--deep .ol-cat-all{color:#fff}
.ol-cat--blue .ol-cat-all{color:#fff}
.ol-cat--deep .ol-cat-h:hover .ol-cat-n{color:var(--red)}
.ol-cat--blue .ol-cat-h:hover .ol-cat-n{color:rgba(255,255,255,.72)}

/* ---- light tones: white and pale blue ---- */
/* The white tile keeps a hairline. Without one it dissolves into the bone
   page behind it, and the dark tiles beside it make that obvious. */
.ol-cat--light{background:#fff;border-color:var(--hair)}
.ol-cat--pale{background:var(--pale)}
.ol-cat--light .ol-cat-g{color:var(--navy);opacity:.08}
.ol-cat--pale .ol-cat-g{color:var(--navy);opacity:.11}
.ol-cat--pale .ol-cat-s a{color:var(--granite)}
.ol-cat--pale .ol-cat-all{color:var(--navy)}

/* Deliberately NO tone override at the narrow breakpoints.
   The sequence was checked in all three layouts before it was written: read
   in a straight line it never repeats a tone twice running, so at one column
   it still alternates, and at two the only repeat is a vertical one between
   the first and second rows. Flattening everything back to white on a tablet
   would throw away the change on the two widths where the grid is longest
   and the reader needs the most help telling one tile from the next. */

/* ==========================================================================
   30. THE PRODUCT CAROUSEL  (client, 22 Sep)
   ==========================================================================
   The rail was a scroll box with the browser scrollbar left showing, and on
   Windows that is a grey trough the width of the section with a second one
   down the right-hand side. It is still a scroll box -- swipe, trackpad and
   keyboard all keep working, and it degrades to a plain scrollable row with
   the script blocked -- but the scrollbars are replaced by two buttons.
   ========================================================================== */
.ol-carousel{position:relative}

/* Outside the track, not over the cards. The rail already runs to the edge of
   the container, so a button sitting on top of it covers a price. */
.ol-carousel-btn{position:absolute;top:120px;z-index:4;
  width:44px;height:44px;border-radius:50%;border:1px solid var(--hair);
  background:#fff;color:var(--navy);display:grid;place-items:center;
  cursor:pointer;box-shadow:var(--e2);transition:.2s var(--ease)}
.ol-carousel-prev{left:-22px}
.ol-carousel-next{right:-22px}
.ol-carousel-btn:hover{background:var(--navy);color:#fff;border-color:var(--navy)}
.ol-carousel-btn:focus-visible{outline:2px solid var(--red);outline-offset:2px}

/* Hidden rather than greyed at the ends. A disabled control that stays put is
   honest on a form, where the reader is looking for it; on a carousel it is
   just a dead circle beside the first card. */
.ol-carousel-btn[hidden]{display:none}
.ol-carousel-btn svg{width:18px;height:18px}
.ol-carousel-prev svg{transform:rotate(180deg)}

/* The buttons are printed with the hidden attribute and unhidden by
   wireCarousels() once it has measured the overflow. This is the belt to
   that braces: if the script never runs at all, they stay out of the
   layout rather than sitting there doing nothing. */
.ol-carousel:not([data-ol-ready]) .ol-carousel-btn{display:none}

/* Under 1500px the container gutter is narrower than the button, so a button
   hung outside the track would be cut off by the viewport. They come inside
   and sit over the corner of the artwork, which is the one part of the card
   with nothing to read on it. */
@media(max-width:1500px){
  .ol-carousel-prev{left:8px}
  .ol-carousel-next{right:8px}
}

/* On a phone the thumb is the control. */
@media(max-width:780px){
  .ol-carousel-btn{display:none!important}
}


/* ==========================================================================
   31. THE PANEL BEHIND THE PHOTOGRAPH  (client, 22 Sep)
   ==========================================================================
   --ol-shot is written onto the card by ol_shot_panel(), from a colour sampled
   off the image border when it was uploaded. It defaults to white, so a product
   with no image, an image that could not be read, or an image whose border is
   too varied to match all keep exactly what they had.

   The SKU sits on this panel, so it has to move with it.
   ========================================================================== */
.ol-pshot--dark .ol-code{color:rgba(255,255,255,.62)}

/* The 12px inset is what stops a cut-out touching the card edge. On a matched
   panel it is invisible, and on a dark one it would draw a light frame around
   the photograph -- exactly the edge this was meant to remove -- so it goes. */
.ol-pshot--dark img{padding:0}

/* ==========================================================================
   32. HOVER COLOUR ON LINKS  (30 Sep)

   The base rule near the top of this file now holds a:hover at inherit,
   which is what Hello reset.css was overriding. Anything that inherits its
   colour is correct from that one line. This section is the other case:
   components that set a colour of their own from a single class, at 0-1-0.
   Those lose to the 0-1-1 neutraliser, so each one states the colour it is
   meant to keep. Nothing here is a new hover effect -- every value is the
   component resting colour, held through the hover.
   ========================================================================== */

.ol-btn-red:hover,.ol-btn-red:active,
.ol-btn-navy:hover,.ol-btn-navy:active,
.ol-btn-ghost:hover,.ol-btn-ghost:active{color:#fff}
.ol-btn-line:hover,.ol-btn-line:active{color:var(--navy)}

/* The tile tones are 0-2-0 and were never caught by the reset, but a bare
   .ol-cat-all:hover at 0-2-0 would now outrank them, so they come along. */
.ol-cat-all:hover,.ol-cat-all:active{color:var(--navy)}
.ol-cat--deep .ol-cat-all:hover,.ol-cat--deep .ol-cat-all:active{color:#fff}
.ol-cat--blue .ol-cat-all:hover,.ol-cat--blue .ol-cat-all:active{color:#fff}
.ol-cat--pale .ol-cat-all:hover,.ol-cat--pale .ol-cat-all:active{color:var(--navy)}

.ol-chip:hover,.ol-chip:active{color:var(--navy)}
.ol-fx-clear:hover,.ol-fx-clear:active{color:var(--red)}
.ol-ico:hover,.ol-ico:active{color:var(--navy)}
.ol-sd-all:hover,.ol-sd-all:active{color:var(--red)}

/* ==========================================================================
   33. THE WHITE SLAB ON A FOCUSED FIELD  (30 Sep)

   Hello reset.css draws focus as two layers:

     input:focus-visible{box-shadow:0 0 0 4px #fff;outline:2px solid #000}

   The white ring is spacing between the black outline and the field. This
   theme shows focus on the wrapper instead -- .ol-srch:focus-within takes a
   navy border, the drawer field inverts to white -- so each of these inputs
   sets outline:0. That cancelled the outline. Nothing cancelled the ring,
   which carries the same 0-1-1 weight as our own rule and so survived it,
   and on click it painted a 4px white slab across the wrapper border.
   It leaves with the outline it belonged to. Every field not named here
   keeps the Hello treatment whole, which is the reason for naming them.
   ========================================================================== */

.ol-srch input:focus-visible,
.ol-side-srch input:focus-visible,
.ol-herosearch input:focus-visible,
.ol-pbox .quantity input.qty:focus-visible{box-shadow:none}


/* ==========================================================================
   BRANDS INDEX  (page-brands.php)
   The marks are white knockout artwork drawn for the dark strip, so each one
   sits on its own navy panel rather than on the page ground.
   ========================================================================== */
.ol-brandslede{margin:26px 0 0}
.ol-brandsgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin:30px 0 64px}
@media(max-width:1040px){.ol-brandsgrid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:760px){.ol-brandsgrid{grid-template-columns:repeat(2,1fr);gap:14px}}
.ol-brandcard{display:block;border:1px solid #D8D4CC;border-radius:6px;overflow:hidden;background:#fff;text-decoration:none;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.ol-brandcard:hover,.ol-brandcard:focus-visible{transform:translateY(-2px);box-shadow:0 10px 26px rgba(0,0,0,.10);border-color:#C6C1B6}
.ol-brandmark{display:flex;align-items:center;justify-content:center;background:var(--navy,#002D52);padding:28px 22px;min-height:112px}
.ol-brandmark img{max-width:74%;max-height:48px;width:auto;height:auto;object-fit:contain}
.ol-brandmark b{color:#fff;font-size:19px;font-weight:700;text-transform:uppercase;letter-spacing:.02em;text-align:center}
.ol-brandmeta{display:block;padding:14px 16px 16px}
.ol-brandmeta strong{display:block;font-size:15px;line-height:1.3;color:#1b1b1b;margin-bottom:3px}
.ol-brandmeta span{display:block;font-size:13px;color:var(--granite,#4A4F5A)}
@media(prefers-reduced-motion:reduce){.ol-brandcard{transition:none}.ol-brandcard:hover{transform:none}}


/* ---- Sticky header -------------------------------------------------------
   .ol-hdr already declares position:sticky, but it never worked. A sticky
   element can only travel inside its containing block, and every ancestor
   between .ol-hdr and <body> -- the widget container, the widget, the
   Elementor container and the header wrapper -- is exactly 67px tall, the
   height of the bar itself. Zero travel, so it scrolled away like a static
   element on every page.

   The travel has to come from an element whose own parent is tall, so the
   outermost Elementor header wrapper is made sticky; its parent is <body>.
   The inner bar keeps its sticky declaration, which is now harmless, and
   keeps its blur and its border.

   z-index 60 matches what .ol-hdr already used, which keeps it under the
   browse drawer at 200 so an open menu still covers the header.
   -------------------------------------------------------------------------- */
header.elementor-location-header{position:sticky;top:0;z-index:60}

/* An in-page jump now lands 67px under the sticky header, so the top of the
   target is hidden. scroll-padding-top on the scroll container fixes every
   anchor at once -- #bs-shop, #td-find and anything added later -- without
   a scroll-margin on each one. 84px is the bar plus a little breathing room.
   Applied to html because that is the scrolling element here. */
html{scroll-padding-top:84px}
/* M6: an empty basket shows no count. */
.ol-badge[hidden]{display:none}

/* C2: nothing on the map until the visitor names a place. See the note on
   paintMap in ol-app.js for why this is not just ol-off. */
.ol-mapbox.ol-rest .ol-m-pin{display:none}

/* V3: a card carries no fitment label until a vehicle is set. The span is
   rendered hidden and revealed by resolveFitment(); [hidden] is spelled out
   because .ol-fitl sets display itself and would win over the UA default. */
.ol-fitl[hidden]{display:none}

/* V4: once a vehicle is saved the bar is one line. The four selects are a
   question that has been answered, and repeating it at the top of every page
   is the site asking again. Change reopens them without clearing the vehicle. */
.ol-fitpill.ol-collapsed .ol-inner{display:none}
.ol-fitpill .ol-set{background:var(--navy);border-radius:var(--r3);padding:14px 18px;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;color:#fff;
  box-shadow:0 16px 36px -22px rgba(0,29,54,.55)}
.ol-fitpill .ol-set[hidden]{display:none}
.ol-fitpill .ol-set .ol-k{padding:0;opacity:1;color:rgba(255,255,255,.72)}
.ol-fitpill .ol-set b{font-weight:600;font-size:15px;color:#fff}
.ol-fitpill .ol-set .ol-clr{margin-left:auto}

/* V4 on a phone: "one line" has to mean one line. At 375px the label, the
   vehicle and the button wrap to three rows and the bar is taller collapsed
   than it was open, which is the opposite of the point. The label goes, the
   dot and the name carry it, and a long vehicle name truncates rather than
   pushing Change onto a row of its own. */
@media(max-width:620px){
  .ol-fitpill .ol-set{flex-wrap:nowrap;gap:8px;padding:12px 14px}
  .ol-fitpill .ol-set .ol-k{display:none}
  .ol-fitpill .ol-set b{min-width:0;font-size:14px;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis}
  .ol-fitpill .ol-set .ol-clr{flex:0 0 auto}
}

/* M1: the page is wider than the screen on a phone. Reported as the product
   carousel overflowing. It is not: the rail clips itself correctly. It is the
   fitment bar status pill, which is width:100% from 980px down but keeps the
   white-space:nowrap it needs on a desktop row. "No vehicle saved, 369 parts
   in the catalogue" then measures 377px inside a 316px box and drags the page
   out to 414px on a 390px screen, which is the number in the report. */
@media(max-width:620px){
  .ol-fitpill .ol-st{white-space:normal;flex-wrap:wrap;row-gap:2px;line-height:1.6}
}

/* M2: the quote form ran edge to edge on a phone. The section now carries the
   site gutter on mobile, which fixes the heading and the copy with it. These
   two rules undo the negative-margin gutter Elementor puts around its own
   field rows, which otherwise reaches 5px past the section on both sides and
   leaves the page 395px wide on a 390px screen. */
@media(max-width:620px){
  .ol-form .elementor-form-fields-wrapper{margin-left:0;margin-right:0}
  .ol-form .elementor-field-group{padding-left:0;padding-right:0}
}

/* M4: the line price ran outside the checkout summary card on a phone.

   Two causes, both in WooCommerce block CSS. The summary content is
   display:table with width:100%, which measures against the padded box and
   leaves every row 32px wider than the card it sits in. And the description
   column is a flex item with the default min-width:auto, so it refuses to
   shrink below a long product name and shoves the price out of the row.

   Treating the content as a normal block and letting the description shrink
   puts the price back inside the card. Not scoped to a breakpoint: the row is
   wrong at any width, it is only visible once the card is narrow.

   The class is doubled so these beat WooCommerce own rules, which are the same
   specificity and printed after the theme stylesheet. */
.wc-block-components-order-summary .wc-block-components-order-summary__content.wc-block-components-order-summary__content{display:block;width:auto}
.wc-block-components-order-summary-item__description.wc-block-components-order-summary-item__description{min-width:0}
.wc-block-components-order-summary-item__description .wc-block-components-product-name{overflow-wrap:anywhere}

/* M5: the end of the page is the one place content comes to rest under the
   floating buttons rather than scrolling past them, so the footer buys itself
   the room. Both buttons sit 48px tall at a 14px inset on a phone. */
@media(max-width:620px){
  .ol-ftr{padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))}
}

/* D8. Two products per row on phones. A page of 24 ran about 12,900px at one
   per row, which is thirteen screens of scrolling to reach the pager. Only the
   catalogue grid changes; .ol-grid3 on its own still stacks to one. */
@media(max-width:620px){
  .ol-grid3.ol-catgrid{grid-template-columns:repeat(2,1fr);gap:12px}
}
/* Below 480px a card is under about 215px wide, so its furniture comes down
   with it. From 480 to 620 the cards are desktop width and keep desktop type. */
@media(max-width:480px){
  .ol-grid3.ol-catgrid .ol-pb{padding:12px 12px 14px}
  .ol-grid3.ol-catgrid .ol-pbrand{font-size:10px;letter-spacing:.06em;margin-bottom:6px}
  .ol-grid3.ol-catgrid .ol-pname{font-size:13px;margin-bottom:8px;min-height:0;
    display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
  .ol-grid3.ol-catgrid .ol-pfoot{padding-top:11px;gap:6px}
  .ol-grid3.ol-catgrid .ol-price{font-size:16px}
  .ol-grid3.ol-catgrid .ol-add:not(.ol-add-enq){width:34px;height:34px;font-size:15px}
  .ol-grid3.ol-catgrid .ol-code{left:10px;bottom:8px;font-size:10px}
  .ol-grid3.ol-catgrid .ol-fitl{font-size:10px;padding:3px 7px;gap:5px}
  .ol-grid3.ol-catgrid .ol-wish{top:9px;right:9px}
}

/* The From on a variable price had no styling, so it read as part of the
   number. At two per row it also pushed R85 475 onto a second line. */
.ol-price .ol-from{display:block;font-family:var(--mono);font-size:10.5px;
  font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--dust);
  line-height:1.2;margin-bottom:2px}

/* B4. An enquiry-only card used to show a price, a grey circle and a 16px
   arrow, which is the card a buyable product gets. The button now says what
   it does. */
.ol-add.ol-add-enq{width:auto;height:34px;border-radius:999px;padding:0 14px;
  font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  font-weight:700;background:var(--navy);color:#fff;white-space:nowrap}
.ol-add.ol-add-enq:hover{background:var(--red);color:#fff;transform:none}
.ol-enq-note{margin:0 0 14px;font-size:14px;line-height:1.55;color:var(--granite)}

/* On a 167px card there is not room for a price and a pill side by side, so
   the pill takes its own line. Only the 86 enquiry cards pay the height. */
@media(max-width:480px){
  .ol-grid3.ol-catgrid .ol-pfoot{flex-wrap:wrap}
  .ol-grid3.ol-catgrid .ol-add.ol-add-enq{width:100%;height:36px;margin-top:10px}
}

/* The vehicle bar status line is a flex item carrying white-space:nowrap with
   nothing allowing it to shrink, so at 1280 it ran 25px past the viewport and
   put a horizontal scrollbar on every catalogue page. M1 fixed the phone case
   only. The row wraps now, so the status line drops onto a line of its own
   when the selects and the button have taken the width. Above 1620px
   everything still fits on one line and nothing moves. */
@media(max-width:1620px){
  .ol-fitpill .ol-inner{flex-wrap:wrap;border-radius:var(--r);padding:12px 14px}
  .ol-fitpill select{flex:1 1 118px;min-width:0}
  .ol-fitpill .ol-st{margin-left:0;width:100%;justify-content:flex-start}
}


/* M8: search icon in the header wherever the search pill is hidden (1180px
   and below). It opens the drawer with its search field focused. */
.ol-srchbtn{display:none;cursor:pointer;font:inherit;padding:0}
@media(max-width:1180px){
  .ol-srchbtn{display:grid}
}

/* T1: the headline Google rating, printed by the page so it shows with no
   third-party script and before cookie consent. */
.ol-gr-sum{display:inline-flex;align-items:center;gap:14px;text-decoration:none;color:var(--navy);
  background:#fff;border:1px solid var(--hair);border-radius:var(--r);padding:12px 18px;flex-shrink:0;
  transition:.22s var(--ease)}
a.ol-gr-sum:hover{border-color:var(--navy);box-shadow:var(--e1)}
a.ol-gr-sum:focus-visible{outline:2px solid var(--navy);outline-offset:2px}
.ol-gr-sum-n{font-family:var(--display,inherit);font-weight:800;font-size:34px;line-height:1}
.ol-gr-sum-r{display:flex;flex-direction:column;gap:5px}
.ol-gr-sum-st{position:relative;display:inline-block;font-size:17px;line-height:1;letter-spacing:2px;color:var(--bone3)}
.ol-gr-sum-st::before{content:'\2605\2605\2605\2605\2605'}
.ol-gr-sum-st::after{content:'\2605\2605\2605\2605\2605';position:absolute;left:0;top:0;width:var(--ol-pct,0);
  overflow:hidden;white-space:nowrap;color:#F5A623}
.ol-gr-sum-c{font-family:var(--mono);font-size:11.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--granite)}
@media(max-width:620px){
  .ol-gr-sum{margin-top:16px;padding:10px 14px;gap:12px}
  .ol-gr-sum-n{font-size:28px}
}

/* The card hover spins the + on a buy button 90 degrees. The Enquire pill shares
   .ol-add, so it was being turned on its side too. Colour change only. */
.ol-pc:hover .ol-add.ol-add-enq,.ol-add.ol-add-enq:hover,.ol-add.ol-add-enq:focus-visible{transform:none}
/* Same spin hit the arrow on View buttons (variable, coming soon, out of stock),
   turning it to point down. Only the + of a real add to basket turns. */
.ol-pc:hover .ol-add:not(.add_to_cart_button){transform:none}

/* Elementor preview: widgets re-render after the reveal observer has run, so
   their .ol-rv nodes never got .ol-in and the canvas looked empty. No reveal
   animation inside the editor. */
.elementor-editor-active .ol-rv,.elementor-editor-preview .ol-rv{opacity:1!important;transform:none!important}

/* Footer gained an Explore column on 22 Oct: logo plus six menu columns. The
   grid follows the number of columns instead of assuming five. */
@media(min-width:981px){
  .ol-ftr .ol-cols{grid-template-columns:1.4fr;grid-auto-flow:column;grid-auto-columns:1fr;gap:24px}
}
@media(min-width:621px) and (max-width:980px){
  .ol-ftr .ol-cols{grid-template-columns:repeat(3,1fr)}
  .ol-ftr .ol-cols>div:first-child{grid-column:1/-1}
}

/* Back order made to stand out (Reinard, 22 Oct): amber, bold, on the card
   tag and on the product page stock line. */
.ol-tg.ol-tg-bo{background:#F5A623;color:#001D36;font-weight:800}
.ol-spec.ol-stk.ol-stk-onbackorder{display:inline-block;background:#FFF3D6;color:#6B4400;border:1.5px solid #F5A623;border-radius:999px;padding:6px 12px;font-size:13px;font-weight:800;letter-spacing:.04em}

/* POPIA notice on the contact, quote and enquiry forms (22 Oct). */
.ol-form-privacy{margin:4px 0 0;font-size:13px;line-height:1.5;color:var(--granite)}
.ol-form-privacy a{color:var(--navy);text-decoration:underline}

/* ---- Journal: previous / next article navigation ---- */
.ol-pn{margin:56px 0 24px;padding-top:32px;border-top:1px solid var(--hair);font-family:var(--body)}
.ol-pn-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.ol-pn-card{display:flex;align-items:center;gap:16px;padding:14px;border:1px solid var(--hair);border-radius:var(--r);background:var(--white);color:var(--navy)!important;text-decoration:none!important;transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.ol-pn-card:hover{border-color:var(--navy);box-shadow:var(--e2)}
.ol-pn-card:focus-visible{outline:2px solid var(--red);outline-offset:3px}
.ol-pn-next{flex-direction:row-reverse;text-align:right}
.ol-pn-empty{border:0;background:none;padding:0}
.ol-pn-thumb{flex:0 0 96px;width:96px;height:72px;border-radius:var(--r2);overflow:hidden;background:var(--bone)}
.ol-pn-thumb img.ol-pn-img{width:100%;height:100%;object-fit:cover;display:block;margin:0}
.ol-pn-txt{display:flex;flex-direction:column;gap:4px;min-width:0}
.ol-pn-lab{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--red)}
.ol-pn-title{font-weight:800;font-size:16px;line-height:1.3;color:var(--navy)}
.ol-pn-date{font-size:13px;color:var(--granite)}
.ol-pn-all{margin:20px 0 0;text-align:center}
.ol-pn-all a{display:inline-flex;align-items:center;min-height:44px;padding:0 22px;border:1.5px solid var(--navy);border-radius:var(--r3);font-weight:800;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--navy)!important;text-decoration:none!important;transition:background .2s,color .2s}
.ol-pn-all a:hover{background:var(--navy);color:var(--white)!important}
@media(max-width:620px){.ol-pn-grid{grid-template-columns:1fr}.ol-pn-empty{display:none}.ol-pn-thumb{flex-basis:80px;width:80px;height:64px}}

/* ---- Journal: single article reading column ---- */
body.single-post main.site-main{max-width:780px;margin:0 auto;padding:48px 20px 24px;box-sizing:border-box}
body.single-post .page-content img{max-width:100%;height:auto;border-radius:var(--r2)}
body.single-post .ol-pn .ol-pn-thumb img.ol-pn-img{width:100%;height:100%;object-fit:cover;border-radius:0}
@media(max-width:620px){body.single-post main.site-main{padding:28px 16px 16px}}

/* ==========================================================================
   Journal listing (/journal/ and category archives) -- inc/journal-list.php
   Desktop 3 columns >=1025px, tablet 2 columns 621-1024px, mobile 1 column.
   ========================================================================== */
.ol-journal{padding-bottom:72px}
.ol-jl-lead{margin:16px 0 0;max-width:56ch;font-size:16px;line-height:1.6;color:rgba(255,255,255,.78)}
.ol-jl-chips{display:flex;flex-wrap:wrap;gap:10px;margin:28px 0 30px}
.ol-jl-chip{display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 16px;border:1px solid var(--hair);border-radius:var(--r3);background:#fff;font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--navy)!important;text-decoration:none!important;transition:.22s var(--ease)}
.ol-jl-chip:hover{border-color:var(--navy)}
.ol-jl-chip.is-on{background:var(--navy);border-color:var(--navy);color:#fff!important}
.ol-jl-n{font-size:10.5px;opacity:.6}
.ol-jl-chip:focus-visible,.ol-jc a:focus-visible{outline:2px solid var(--red);outline-offset:3px}

.ol-jl-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}
.ol-jc{display:flex;flex-direction:column;background:#fff;border:1px solid var(--hair);border-radius:var(--r);overflow:hidden;transition:border-color .25s var(--ease),box-shadow .25s var(--ease),transform .25s var(--ease)}
.ol-jc:hover{border-color:rgba(0,45,82,.3);box-shadow:var(--e2)}
.ol-jc-media{display:block;position:relative;aspect-ratio:16/10;overflow:hidden;background:var(--bone)}
.ol-journal .ol-jc-media img.ol-jc-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;margin:0;border-radius:0;transition:transform .6s var(--ease)}
.ol-jc:hover .ol-jc-media img.ol-jc-img{transform:scale(1.04)}
.ol-jc-ph{position:absolute;inset:0;display:grid;place-items:center;background:linear-gradient(140deg,var(--navy),var(--deep))}
.ol-jc-ph span{font-family:var(--ol-display);font-style:italic;text-transform:uppercase;font-size:22px;color:rgba(255,255,255,.22)}
.ol-jc-body{display:flex;flex-direction:column;gap:10px;padding:22px 22px 20px;flex:1}
.ol-jc-cat{font-size:11px}
.ol-jc-title{margin:0;font-family:var(--body);font-weight:800;font-style:normal;text-transform:none;font-size:19px;line-height:1.3;letter-spacing:-.005em}
.ol-jc-title a{color:var(--navy)!important;text-decoration:none!important}
.ol-jc-title a::after{content:"";position:absolute;inset:0}
.ol-jc{position:relative}
.ol-jc-media{z-index:0}
.ol-jc-title a:hover{color:var(--red)!important}
.ol-jc-exc{margin:0;font-size:14.5px;line-height:1.6;color:var(--granite);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.ol-jc-meta{margin-top:auto;padding-top:10px;display:flex;gap:8px;flex-wrap:wrap;font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--dust)}

/* Feature card: newest article, image left, copy right */
.ol-jc-feature{flex-direction:row;margin-bottom:24px}
.ol-jc-feature .ol-jc-media{flex:0 0 58%;aspect-ratio:auto;min-height:360px}
.ol-jc-feature .ol-jc-body{padding:40px 40px 34px;justify-content:center;gap:14px}
.ol-jc-feature .ol-jc-title{font-family:var(--ol-display);font-weight:400;font-style:italic;text-transform:uppercase;font-size:clamp(26px,2.6vw,36px);line-height:1;letter-spacing:-.02em}
.ol-jc-feature .ol-jc-exc{font-size:16px;-webkit-line-clamp:4}

.ol-jl-empty{margin:20px 0 40px;font-size:16px;color:var(--granite)}
.ol-journal .ol-pag{justify-content:center}

/* Tablet */
@media(max-width:1024px){
  .ol-jl-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}
  .ol-jc-feature .ol-jc-media{flex-basis:50%;min-height:300px}
  .ol-jc-feature .ol-jc-body{padding:30px 28px}
}
/* Mobile */
@media(max-width:620px){
  .ol-journal{padding-bottom:48px}
  .ol-jl-chips{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;margin:22px -22px 22px;padding:0 22px}
  .ol-jl-chips::-webkit-scrollbar{display:none}
  .ol-jl-chip{flex:0 0 auto}
  .ol-jl-grid{grid-template-columns:1fr;gap:16px}
  .ol-jc-feature{flex-direction:column;margin-bottom:16px}
  .ol-jc-feature .ol-jc-media{flex:none;aspect-ratio:16/10;min-height:0}
  .ol-jc-feature .ol-jc-body{padding:22px 20px 20px}
  .ol-jc-feature .ol-jc-title{font-size:26px}
  .ol-jc-feature .ol-jc-exc{font-size:15px;-webkit-line-clamp:3}
  .ol-jc-body{padding:20px 20px 18px}
  .ol-jc-title{font-size:18px}
  .ol-jl-lead{font-size:15px}
}
@media(prefers-reduced-motion:reduce){.ol-jc,.ol-jc-media img.ol-jc-img{transition:none}.ol-jc:hover .ol-jc-media img.ol-jc-img{transform:none}}

/* ---- Checkout fields: one label style, room between label and value (23 Oct) ---- */
.wc-block-components-text-input label,
.wc-blocks-components-select .wc-blocks-components-select__label{font-family:var(--mono)!important;font-size:10.5px!important;text-transform:uppercase!important;letter-spacing:.07em!important;color:var(--navy)!important;left:18px!important;line-height:1.2!important}
.wc-block-components-text-input.is-active label{top:9px!important;transform:none!important}
.wc-block-components-text-input.is-active input,
.wc-block-components-text-input.is-active textarea{padding-top:23px!important;padding-bottom:6px!important}
.wc-blocks-components-select .wc-blocks-components-select__label{top:9px!important;transform:none!important}
.wc-blocks-components-select .wc-blocks-components-select__select{padding-top:23px!important;padding-bottom:6px!important;padding-left:18px!important}
