/*
Theme Name:   RR Electrical Services — Astra Child
Theme URI:    https://rrelectricalservices.com.sg/
Description:  Child theme for RR Electrical Services. Carries the brand tokens (theme.json),
              the homepage design system, and the persistent call and WhatsApp
              actions. Built per docs/superpowers/specs/ and the approved design
              reference at docs/design/homepage-preview.html.
Author:       RR Electrical Services
Template:     astra
Version:      0.5.1
License:      GPL-2.0-or-later
Text Domain:  astra-child-rr
*/

/* ==========================================================================
   TOKEN ALIASES

   Colour values live in theme.json, which emits them as
   --wp--preset--color--*. They are aliased to short semantic names here so the
   rules below stay readable and match the design reference one-to-one.

   Never hardcode a hex below this block. Spec §10.
   ========================================================================== */
:root {
  --navy:          var(--wp--preset--color--brand);
  --navy-2:        var(--wp--preset--color--brand-2);
  --on-navy:       var(--wp--preset--color--on-brand);
  --on-navy-soft:  var(--wp--preset--color--on-brand-soft);

  --action:        var(--wp--preset--color--action);
  --action-hover:  var(--wp--preset--color--action-hover);
  --action-tint:   var(--wp--preset--color--action-tint);
  --on-action:     var(--wp--preset--color--on-action);

  --electrical:      var(--wp--preset--color--electrical);
  --electrical-ink:  var(--wp--preset--color--electrical-ink);
  --electrical-tint: var(--wp--preset--color--electrical-tint);
  --plumbing:        var(--wp--preset--color--plumbing);
  --plumbing-ink:    var(--wp--preset--color--plumbing-ink);
  --plumbing-tint:   var(--wp--preset--color--plumbing-tint);
  --aircon:          var(--wp--preset--color--aircon);
  --aircon-ink:      var(--wp--preset--color--aircon-ink);
  --aircon-tint:     var(--wp--preset--color--aircon-tint);

  --wa:      var(--wp--preset--color--wa);
  --wa-ink:  var(--wp--preset--color--wa-ink);

  --bg:          var(--wp--preset--color--surface);
  --surface:     var(--wp--preset--color--base);
  --surface-alt: var(--wp--preset--color--surface-alt);
  --ink:         var(--wp--preset--color--ink);
  --ink-soft:    var(--wp--preset--color--ink-soft);
  --border:      var(--wp--preset--color--border);

  /* Crisp micro-shadow: modern cards read as edges, not smudges. The old
     18px/40px diffuse shadow was the single biggest "2015" tell. */
  --shadow: 0 1px 2px rgb(11 37 69 / 6%), 0 8px 20px -14px rgb(11 37 69 / 18%);
  --shadow-lift: 0 2px 4px rgb(11 37 69 / 7%), 0 16px 32px -16px rgb(11 37 69 / 28%);
  --radius: 16px;

  /* The signature: a live busbar running blue -> logo orange.
     Naive RGB interpolation between these two hues passes through a muddy
     olive, so the fallback keeps the blend window short; browsers with oklch
     gradient support get the full smooth sweep. */
  --busbar: linear-gradient(90deg, var(--aircon) 0%, var(--aircon) 42%, var(--electrical) 58%, var(--electrical) 100%);

  --font-mono: var(--wp--preset--font-family--mono);

  /* height of the fixed mobile action bar; the body reserves this much */
  --rr-bar-h: 58px;
}

/* ==========================================================================
   BASE
   ========================================================================== */
body.sk {
  background: var(--bg);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.6;
}

.sk .display {
  font-family: var(--wp--preset--font-family--display);
  font-weight: 800;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.sk .eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.72rem;
  font-weight: 700;
  display: inline-flex; align-items: center; gap: 10px;
}
/* every eyebrow opens with a short orange trace — the busbar motif at echo scale */
.sk .eyebrow::before {
  content: ""; width: 22px; height: 2px; border-radius: 2px;
  background: var(--electrical); flex: none;
}

.sk .kicker { color: var(--electrical-ink); margin: 0 0 12px; }
.sk .tnum   { font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

.sk img, .sk svg { display: block; max-width: 100%; }
.sk a { color: inherit; text-decoration: none; }

.rr-container { max-width: 1180px; margin: 0 auto; padding: 0 48px; }
.rr-section   { padding: 84px 0; }
.rr-section--alt { background: var(--surface-alt); }

.sk h2.display { font-size: 2.35rem; }
.sk p.lede { color: var(--ink-soft); font-size: 1.05rem; max-width: 52ch; margin: 14px 0 0; }

.rr-icon { width: 18px; height: 18px; }

/* skip link — keyboard users must be able to jump past the sticky nav */
.rr-skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--action); color: var(--on-action);
  padding: 12px 20px; font-weight: 700;
}
.rr-skip:focus { left: 0; }

/* ==========================================================================
   BUTTONS

   .rr-call is the single reusable call pattern. Spec §9 defers call tracking
   specifically so it can be added here once rather than across every page.

   Label contrast: white on the action red-orange measures 4.91:1, which clears
   WCAG AA for normal text. Do not change either colour without re-measuring.
   ========================================================================== */
.rr-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 13px 26px; border-radius: 999px;   /* pill: the modern trade-service CTA */
  font-family: var(--wp--preset--font-family--display);
  font-weight: 700; font-size: 0.95rem; letter-spacing: 0.005em;
  border: 1.5px solid transparent;
  min-height: 48px;               /* spec §4: tap targets at least 48x48 */
  cursor: pointer;
  white-space: nowrap;            /* a phone number that wraps reads as two numbers */
}
.rr-btn .rr-icon { width: 18px; height: 18px; }

/* The phone glyph floats weightlessly on a filled pill, so call buttons set it
   in a small white coin — reads as a deliberate mark, not a stray outline. */
.sk .rr-btn--call .rr-icon,
.sk .rr-btn--navy .rr-icon {
  width: 24px; height: 24px; padding: 5px; box-sizing: border-box;
  border-radius: 50%; flex: none;
  background: rgb(255 255 255 / 94%);
}
.sk .rr-btn--call .rr-icon { color: var(--action); }
.sk .rr-btn--navy .rr-icon { color: var(--navy); }

/*
   Every colour rule below is prefixed with `.sk`.

   The base reset `.sk a { color: inherit }` scores (0,1,1) and beats a bare
   `.rr-btn--navy` at (0,1,0), so buttons inherited the surrounding text colour
   instead of their own — navy text on a navy button in the package cards, and
   dark text on the orange call button anywhere outside a dark band. It looked
   correct only inside the navy sections, where the inherited colour happened to
   be light. Two classes (0,2,0) puts these back in charge.
*/
.sk .rr-btn--call {
  background: var(--action); color: var(--on-action);
  box-shadow: 0 1px 2px rgb(214 71 9 / 30%), 0 10px 22px -10px rgb(214 71 9 / 50%);
}
.sk .rr-btn--call:hover, .sk .rr-btn--call:focus {
  background: var(--action-hover); color: var(--on-action);
  transform: translateY(-1px);
}

.sk .rr-btn--outline { background: transparent; color: var(--ink); border-color: var(--border); }
.sk .rr-btn--outline:hover { border-color: var(--ink-soft); }

.sk .rr-btn--navy { background: var(--navy); color: var(--on-navy); }
.sk .rr-btn--navy:hover { background: var(--navy-2); color: var(--on-navy); }

/* WhatsApp is deliberately secondary weight — outlined, never filled. Spec §9
   ranks it below the call action, and nothing may outrank a call. */
.sk .rr-btn--wa { background: transparent; color: var(--wa-ink); border-color: var(--wa); }

.rr-btn:focus-visible { outline: 2px solid var(--aircon); outline-offset: 2px; }

.rr-tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
.rr-tag--elec  { background: var(--electrical-tint); color: var(--electrical-ink); }
.rr-tag--plumb { background: var(--plumbing-tint);   color: var(--plumbing-ink); }
.rr-tag--air   { background: var(--aircon-tint);     color: var(--aircon-ink); }

/* ==========================================================================
   HEADER
   ========================================================================== */
/* Light header (2026-08-17): the emblem artwork was drawn for white ground, so
   the header ground is white — the same call the owner's reference site makes.
   The busbar keeps the top edge; a hairline + soft shadow keep the sticky bar
   separated from the light sections it passes over. */
.rr-header {
  position: sticky; top: 0; z-index: 20;
  background: var(--surface); color: var(--ink);
  box-shadow: 0 1px 0 var(--border), 0 10px 24px -20px rgb(11 37 69 / 30%);
}
/* the live busbar: the site's one signature line, full-width across the top */
.rr-header::before { content: ""; display: block; height: 3px; background: var(--busbar); }
.rr-header__row { display: flex; align-items: center; gap: 26px; padding: 11px 0; }

.rr-brand { display: flex; align-items: center; gap: 10px; margin-right: 6px; min-width: 0; }
.rr-brand img, .rr-brand svg { height: 38px; width: auto; flex: none; }

/* Mobile call strip. Spec §9 requires the number visible on first paint at every
   viewport and explicitly NOT hidden behind the hamburger. Putting it in its own
   strip keeps it visible without crowding the logo row. */
.rr-callstrip { display: none; }

.rr-nav { display: flex; gap: 20px; align-items: center; margin-right: auto; }
.rr-nav > li { position: relative; list-style: none; }
.rr-nav a {
  font-size: 0.85rem; font-weight: 600; color: var(--ink-soft);
  display: flex; align-items: center; gap: 4px; padding: 8px 0;
  white-space: nowrap;   /* two-line nav items read as broken, not wrapped */
}
.rr-nav a:hover, .rr-nav a:focus-visible { color: var(--navy); }

/* Dropdown: a proper panel, not a floating list. The busbar clips its top
   edge (same signature as the header it hangs from), items get a sliding
   orange trace on hover, and a 10px invisible bridge covers the hover gap
   between the link and the panel so it cannot flicker shut in transit. */
.rr-nav .sub-menu {
  position: absolute; top: calc(100% + 10px); left: -18px; min-width: 264px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-lift);
  padding: 10px; margin: 0; list-style: none;
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
  overflow: hidden;
}
.rr-nav .sub-menu::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--busbar);
}
.rr-nav .sub-menu::after {
  content: ""; position: absolute; top: -10px; left: 0; right: 0; height: 10px;
}
.rr-nav li:hover > .sub-menu,
.rr-nav li:focus-within > .sub-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.rr-nav .sub-menu a {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 12px; border-radius: 8px;
  font-size: 0.85rem; color: var(--ink); font-weight: 500;
  white-space: nowrap;
}
.rr-nav .sub-menu a::before {
  content: ""; width: 0; height: 2px; border-radius: 2px;
  background: var(--electrical);
  transition: width 0.16s ease;
  flex: none;
}
.rr-nav .sub-menu a:hover,
.rr-nav .sub-menu a:focus-visible { background: var(--surface-alt); color: var(--navy); }
.rr-nav .sub-menu a:hover::before,
.rr-nav .sub-menu a:focus-visible::before { width: 14px; }

/* Between tablet-landscape and small laptop the six no-wrap items plus the call
   button outgrow the row; the type and gaps tighten before anything clips. */
@media (min-width: 782px) and (max-width: 1120px) {
  .rr-header .rr-container { padding: 0 24px; }
  .rr-header__row { gap: 16px; }
  .rr-nav { gap: 13px; }
  .rr-nav a { font-size: 0.78rem; }
  .rr-header .rr-btn { padding: 11px 16px; font-size: 0.85rem; }
}

.rr-burger { display: none; background: transparent; border: 0; color: var(--ink); padding: 6px; }
.rr-burger .rr-icon { width: 24px; height: 24px; }
/*
   The burger becomes an X while the panel is open, so one control does both.

   Note the two-class selectors. The base rule `.sk img, .sk svg { display:block }`
   scores (0,1,1), so a bare `.rr-burger__close { display:none }` at (0,1,0) loses
   to it and BOTH icons render side by side. The open-state rules already scored
   high enough, which is why only the closed state was visibly wrong.
*/
.rr-burger .rr-burger__close { display: none; }
.rr-burger[aria-expanded="true"] .rr-burger__open { display: none; }
.rr-burger[aria-expanded="true"] .rr-burger__close { display: block; }

/*
   Mobile menu.

   A panel anchored under the header, sized to its content — NOT a full-screen
   overlay. With only six links, a full-height sheet is 60% empty space and reads
   as broken. It is a child of .rr-header, so `top:100%` pins it to the bottom of
   the header no matter how tall the call strip makes that.
*/
.rr-drawer {
  display: none;
  position: absolute; top: 100%; left: 0; right: 0; z-index: 40;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 22px 34px -20px rgb(11 37 69 / 40%);
  padding: 6px 20px 18px;
  max-height: calc(100vh - 100%);
  overflow-y: auto;
}
.rr-drawer.is-open { display: block; }

.rr-drawer ul { list-style: none; margin: 0; padding: 0; }  /* kills the default bullets */
.rr-drawer li { margin: 0; }

/*
   Scoped to the MENU list, not every anchor in the panel. `.rr-drawer a` has
   higher specificity than `.rr-btn`, so it was overriding the action buttons'
   `display:inline-flex` with `display:block` and stacking their icon above
   their label.
*/
.rr-drawer__menu a {
  display: block; padding: 14px 2px; font-weight: 700; font-size: 0.95rem;
  color: var(--ink);
  border-bottom: 1px solid var(--border);
}
.rr-drawer__menu li:last-child > a { border-bottom: 0; }
.rr-drawer__menu a:focus-visible { outline: 2px solid var(--electrical); outline-offset: -2px; }

/* The menu doubles as a place to call from, so opening it never costs a step
   toward the phone. Spec §9. */
.rr-drawer__actions { display: flex; gap: 10px; margin-top: 14px; }
.rr-drawer__actions .rr-btn { flex: 1; padding: 12px 14px; font-size: 0.88rem; }

/* Tapping the page behind the panel closes it. */
.rr-scrim { display: none; position: fixed; inset: 0; z-index: 19; background: rgb(0 0 0 / 45%); }
.rr-scrim.is-open { display: block; }

/* ==========================================================================
   PHOTO PLACEHOLDER
   Real photographs replace these at the same aspect ratios, so dropping them in
   causes no layout shift. Spec §10.
   ========================================================================== */
.rr-photo {
  position: relative; border-radius: var(--radius); overflow: hidden;
  min-height: 220px; display: flex; align-items: center; justify-content: center;
}
.rr-photo::after { content: ""; position: absolute; inset: 0; background: linear-gradient(200deg, transparent 30%, rgb(0 0 0 / 35%)); }
.rr-photo > .rr-icon { width: 52px; height: 52px; color: rgb(255 255 255 / 45%); z-index: 1; }
.rr-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.rr-photo.has-img { background: none !important; }
.rr-photo.has-img > .rr-icon { display: none; }
.rr-photo__cap {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  background: rgb(15 26 34 / 70%); color: #fff;
  font-size: 0.68rem; letter-spacing: 0.05em; padding: 6px 10px; border-radius: 999px;
  display: flex; align-items: center; gap: 6px;
}
.rr-photo__cap .rr-icon { width: 12px; height: 12px; color: #fff; }

/* ==========================================================================
   HERO — asymmetric split, deliberately not the reference site's centred band
   ========================================================================== */
.rr-hero { padding: 84px 0 72px; position: relative; overflow: hidden; }
/* faint dot grid — the graph paper a circuit gets drawn on. Barely-there texture,
   clipped to the hero so it stays an accent rather than wallpaper. */
.rr-hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgb(11 37 69 / 7%) 1px, transparent 1px);
  background-size: 26px 26px;
  mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
}
.rr-hero__grid { position: relative; display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 56px; align-items: center; }
.rr-hero h1 { font-size: 3.4rem; line-height: 1.04; margin: 0; }

/* the wire underline: the busbar again, running under the last phrase and
   terminating in a node — a single-line diagram's connection point */
.rr-wire { position: relative; white-space: nowrap; }
.rr-wire::after {
  content: ""; position: absolute; left: 1%; right: 4%; bottom: -0.08em;
  height: 4px; border-radius: 4px; background: var(--busbar);
}
.rr-wire::before {
  content: ""; position: absolute; right: 1.2%; bottom: -0.08em;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--electrical); transform: translateY(3px);
}

.rr-hero__ctas { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 30px; }
.rr-trust { display: flex; gap: 22px; margin-top: 34px; flex-wrap: wrap; }
.rr-trust div { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; font-weight: 600; color: var(--ink-soft); }
.rr-trust .rr-icon { width: 17px; height: 17px; color: var(--electrical); }

/* photo in an offset frame: white matte + orange ring shifted behind it, so the
   image sits like a mounted panel rather than a floating rectangle */
.rr-hero__photo { height: 380px; transform: translateY(-10px); background: linear-gradient(135deg, var(--electrical) 0%, var(--navy) 130%); }
.rr-hero__photo.has-img {
  border: 6px solid var(--surface, #fff);
  outline: 1.5px solid var(--border);
  box-shadow: 14px 14px 0 -2px var(--electrical-tint), var(--shadow-lift);
}

/* --------------------------------------------------------------------------
   FULL-BLEED HERO (homepage) — the photograph IS the section, per the owner's
   reference site. A navy scrim keeps AA contrast for every word on top of it;
   heaviest over the text column, thinnest over the technician on the right.
   -------------------------------------------------------------------------- */
.rr-hero.has-bg {
  position: relative;
  background-size: cover;
  background-position: center right;
  padding: 108px 0 100px;
}
.rr-hero.has-bg::before { display: none; }   /* dot grid has no business on a photo */
.rr-hero.has-bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(97deg,
    rgb(7 24 46 / 93%) 0%,
    rgb(7 24 46 / 84%) 38%,
    rgb(11 37 69 / 55%) 68%,
    rgb(11 37 69 / 28%) 100%);
}
.rr-hero.has-bg .rr-container { position: relative; z-index: 2; }
.rr-hero__content { max-width: 640px; }

/* --------------------------------------------------------------------------
   HERO CAROUSEL — one slide per trade, crossfaded under the scrim.
   Slides are background layers only; the text never moves, so the rotation
   costs no layout shift. Transform/opacity only = compositor-friendly.
   -------------------------------------------------------------------------- */
.rr-hero__slides { position: absolute; inset: 0; overflow: hidden; }
.rr-hero__slide {
  position: absolute; inset: 0;
  background-size: cover; background-position: center right;
  opacity: 0;
  transition: opacity 1.4s ease;
  will-change: opacity, transform;
}
.rr-hero__slide.is-active { opacity: 1; }
/* the scrim (::after) must sit above the slides but below the text */
.rr-hero.has-bg::after { z-index: 1; }

@media (prefers-reduced-motion: no-preference) {
  /* a slow push-in on the live slide — the "3D" depth cue, GPU-only */
  .rr-hero__slide.is-active { animation: rr-kenburns 8s ease-out forwards; }
  @keyframes rr-kenburns {
    from { transform: scale(1) translateX(0); }
    to   { transform: scale(1.07) translateX(-1.2%); }
  }
}

/* --------------------------------------------------------------------------
   CARD TILT — pointer-following 3D on the photo cards. The JS writes
   --tilt-x/--tilt-y custom properties; without JS (or with reduced motion)
   the cards simply never tilt.
   -------------------------------------------------------------------------- */
.rr-triad { perspective: 900px; }
.rr-card.has-media {
  transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transform-style: preserve-3d;
}

.sk .rr-hero.has-bg h1 { color: #fff; }
.rr-hero.has-bg .lede { color: rgb(233 240 248 / 88%); }
.rr-hero.has-bg .kicker { color: var(--electrical); }
.rr-hero.has-bg .rr-trust div { color: rgb(233 240 248 / 80%); }
.sk .rr-hero.has-bg .rr-btn--outline { color: #fff; border-color: rgb(255 255 255 / 45%); }
.sk .rr-hero.has-bg .rr-btn--outline:hover { border-color: #fff; }

/* --------------------------------------------------------------------------
   CARD MEDIA — service triad photographs. The image bleeds to the card edge
   and the trade icon sits half over it, badge-style.
   -------------------------------------------------------------------------- */
.rr-card__media {
  margin: -28px -28px 0;
  height: 172px;
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
}
.rr-card__media img { width: 100%; height: 100%; object-fit: cover; }
.rr-card.has-media .rr-card__bar { display: none; }  /* the photo replaces the bar */
.rr-card.has-media .rr-card__ic {
  margin-top: -23px;
  position: relative;
  border: 3px solid var(--surface);
  box-shadow: var(--shadow);
}
@media (prefers-reduced-motion: no-preference) {
  .rr-card__media img { transition: transform 0.35s ease; }
  .rr-card:hover .rr-card__media img { transform: scale(1.04); }
}

/* ==========================================================================
   SERVICE TRIAD — staggered, so it is not a uniform 3-up grid. Spec §4.1
   ========================================================================== */
.rr-triad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.rr-triad .rr-card:nth-child(1) { transform: translateY(-14px); }
.rr-triad .rr-card:nth-child(3) { transform: translateY(14px); }

.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow); }
.rr-card:hover { box-shadow: var(--shadow-lift); border-color: rgb(11 37 69 / 16%); }
.rr-card__bar { height: 4px; width: 44px; border-radius: 99px; margin-bottom: 16px; }
.rr-card__ic { width: 46px; height: 46px; border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-bottom: 14px; }
.rr-card__ic .rr-icon { width: 24px; height: 24px; }
.rr-card h3 { font-size: 1.15rem; margin: 0; }
.rr-card p { color: var(--ink-soft); font-size: 0.92rem; margin: 8px 0 14px; }
.rr-card__go { font-size: 0.84rem; font-weight: 700; display: inline-flex; align-items: center; gap: 5px; }

.rr-card--elec  .rr-card__bar { background: var(--electrical); }
.rr-card--elec  .rr-card__ic  { background: var(--electrical-tint); color: var(--electrical-ink); }
.rr-card--elec  .rr-card__go  { color: var(--electrical-ink); }
.rr-card--plumb .rr-card__bar { background: var(--plumbing); }
.rr-card--plumb .rr-card__ic  { background: var(--plumbing-tint); color: var(--plumbing-ink); }
.rr-card--plumb .rr-card__go  { color: var(--plumbing-ink); }
.rr-card--air   .rr-card__bar { background: var(--aircon); }
.rr-card--air   .rr-card__ic  { background: var(--aircon-tint); color: var(--aircon-ink); }
.rr-card--air   .rr-card__go  { color: var(--aircon-ink); }

/* ==========================================================================
   QUOTE / CALL SPLIT
   ========================================================================== */
.rr-split { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 40px; align-items: start; }
.rr-callcard { background: linear-gradient(150deg, var(--navy) 40%, var(--navy-2) 100%); color: var(--on-navy); border-radius: var(--radius); padding: 30px; position: sticky; top: 92px; overflow: hidden; }
/* the busbar clips the card's top edge, tying the call panel to the header */
.rr-callcard::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--busbar); }
.rr-callcard__big { font-family: var(--font-mono); font-size: 1.6rem; font-weight: 600; margin: 14px 0 18px; letter-spacing: -0.03em; }
.rr-callcard p { color: var(--on-navy-soft); font-size: 0.88rem; }

.rr-formwrap { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow); }

/* ==========================================================================
   ABOUT
   ========================================================================== */
.rr-about { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 48px; align-items: center; }
.rr-about__photo { height: 300px; background: linear-gradient(135deg, var(--plumbing) 0%, var(--navy) 130%); }
.rr-why { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 14px; }
.rr-why li { display: flex; gap: 12px; align-items: flex-start; font-size: 0.94rem; }
.rr-why .rr-icon { width: 19px; height: 19px; color: var(--plumbing-ink); flex: none; margin-top: 2px; }

/* ==========================================================================
   FEATURED — column flow rather than a uniform grid, so tile weight varies
   ========================================================================== */
.rr-feat { column-count: 3; column-gap: 20px; }
.rr-feat__item { break-inside: avoid; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin: 0 0 20px; }
.rr-feat__item h4 { font-size: 1rem; margin: 10px 0 6px; }
.rr-feat__item p { font-size: 0.85rem; color: var(--ink-soft); margin: 0; }

/* ==========================================================================
   STATS BAND
   ========================================================================== */
.rr-stats { background: linear-gradient(115deg, var(--navy) 30%, var(--navy-2) 100%); color: var(--on-navy); border-top: 3px solid transparent; border-image: var(--busbar) 1; }
.rr-stats__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; text-align: center; }
/* meter numerals: the one place the mono face carries a headline size */
.rr-stat__n { font-family: var(--font-mono); font-size: 2.2rem; font-weight: 600; letter-spacing: -0.04em; }
.rr-stat__l { font-size: 0.78rem; color: var(--on-navy-soft); margin-top: 4px; }
.rr-stats__grid > :nth-child(1) .rr-stat__n { color: var(--electrical); }
.rr-stats__grid > :nth-child(2) .rr-stat__n { color: var(--plumbing); }
.rr-stats__grid > :nth-child(3) .rr-stat__n { color: var(--aircon); }
.rr-stats__grid > :nth-child(4) .rr-stat__n { color: var(--action); }

/*
   Placeholder marker. Spec §3b forbids publishing invented figures, so any stat
   without a verified number renders visibly marked rather than silently faked.
   These must be replaced or the stat cut before launch.
*/
.rr-stat.is-tbc { opacity: 0.62; }
.rr-stat.is-tbc .rr-stat__n::after {
  content: "TBC"; display: inline-block; vertical-align: super;
  font-size: 0.42em; letter-spacing: 0.08em; margin-left: 5px;
  color: #f3a38c; border: 1px dashed #b85238; border-radius: 4px; padding: 1px 4px;
}
.rr-unverified {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--action-tint); color: var(--action);
  border: 1px dashed var(--action);
  padding: 5px 11px; border-radius: 999px;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  margin-bottom: 14px;
}
.rr-stats .rr-unverified { background: rgb(200 67 31 / 18%); color: #f3a38c; border-color: #b85238; }

/* ==========================================================================
   PROCESS
   ========================================================================== */
.rr-process { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; position: relative; }
.rr-process::before { content: ""; position: absolute; top: 22px; left: 6%; right: 6%; height: 1.5px; background: var(--border); }
.rr-step { position: relative; padding-right: 16px; }
.rr-step__num {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--surface); border: 1.5px solid var(--action); color: var(--action);
  display: flex; align-items: center; justify-content: center; font-weight: 700;
  position: relative; z-index: 1;
}
.rr-step h4 { font-size: 0.98rem; margin: 14px 0 6px; }
.rr-step p { font-size: 0.85rem; color: var(--ink-soft); margin: 0; }

/* ==========================================================================
   HDB PACKAGES
   ========================================================================== */
.rr-pkgs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.rr-pkg { background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--radius); padding: 26px; }
.rr-pkg.is-featured { border-color: var(--electrical); box-shadow: 0 0 0 3px var(--electrical-tint); }
.rr-pkg__flat { font-size: 0.78rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.06em; }
.rr-pkg__price { margin: 10px 0 4px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
/* the meter numerals again: price is the one number a visitor compares */
.rr-pkg__amount { font-family: var(--font-mono); font-size: 1.7rem; font-weight: 600; letter-spacing: -0.03em; color: var(--navy); }
/* previous published rate, struck through beside the live price */
.rr-pkg__was { font-size: 0.98rem; color: var(--ink-soft); text-decoration-thickness: 1.5px; }

/* the shared inclusions line that replaced three identical checklists */
.rr-pkgs__includes {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 20px 0 12px;
  font-size: 0.94rem; color: var(--ink-soft);
  max-width: 62ch;
}
.rr-pkgs__includes .rr-icon { width: 18px; height: 18px; color: var(--plumbing-ink); flex: none; margin-top: 3px; }
.rr-pkg ul { list-style: none; padding: 0; margin: 16px 0 20px; display: grid; gap: 9px; }
.rr-pkg li { display: flex; gap: 8px; font-size: 0.85rem; align-items: flex-start; }
.rr-pkg li .rr-icon { width: 15px; height: 15px; color: var(--plumbing-ink); margin-top: 2px; flex: none; }
.rr-pkg__note { display: block; text-align: center; margin-top: 10px; font-size: 0.78rem; color: var(--action); font-weight: 700; }

/* ==========================================================================
   TESTIMONIALS
   ========================================================================== */
.rr-testi { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.rr-stars { display: flex; gap: 3px; color: var(--electrical); margin-bottom: 10px; }
.rr-stars .rr-icon { width: 15px; height: 15px; }
.rr-testi__quote { font-size: 0.92rem; color: var(--ink); }
.rr-testi__who { margin-top: 14px; font-size: 0.8rem; font-weight: 700; color: var(--ink-soft); }

/* Initials instead of a photograph. Spec §3b: a stock headshot beside an invented
   name is the most legally exposed content on a trades site. */
.rr-avatar {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 0.82rem; color: #fff; background: var(--navy-2);
}

/* ==========================================================================
   CONTACT
   ========================================================================== */
.rr-contact { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: center; }
.rr-nap { list-style: none; margin: 20px 0 26px; padding: 0; display: grid; gap: 16px; }
.rr-nap li { display: flex; gap: 12px; font-size: 0.94rem; }
.rr-nap .rr-icon { width: 19px; height: 19px; color: var(--aircon-ink); flex: none; margin-top: 1px; }
.rr-map { height: 260px; border-radius: var(--radius); background: var(--surface-alt); border: 1px solid var(--border); position: relative; overflow: hidden; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.rr-footer { background: var(--navy); color: var(--on-navy-soft); padding-top: 56px; }
.rr-footer__grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr 1fr; gap: 30px; padding-bottom: 36px; border-bottom: 1px solid rgb(255 255 255 / 8%); }
.rr-footer h5 { color: var(--on-navy); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; margin: 0 0 14px; }
.rr-footer a, .rr-footer p { display: block; font-size: 0.86rem; margin: 0 0 10px; overflow-wrap: anywhere; }
.rr-footer ul { list-style: none; margin: 0; padding: 0; }
.rr-footer a:hover { color: var(--on-navy); }
.rr-footer__bottom { display: flex; justify-content: space-between; align-items: center; padding: 20px 0; font-size: 0.76rem; flex-wrap: wrap; gap: 10px; }
.rr-socials { display: flex; gap: 10px; }
.rr-socials a { width: 32px; height: 32px; border-radius: 8px; background: rgb(255 255 255 / 6%); display: flex; align-items: center; justify-content: center; }
.rr-socials .rr-icon { width: 15px; height: 15px; }

/* ==========================================================================
   FLUENT FORMS

   The plugin ships its own blue. Rather than write our hex into the plugin's
   settings — which would duplicate a theme.json token into the database, where a
   rebrand would never reach it — the form is restyled here from the same tokens
   as everything else. Fluent Forms sets no inline styles on these, so ordinary
   specificity is enough and no !important is needed.
   ========================================================================== */
.sk .fluentform .ff-el-group { margin-bottom: 16px; }

.sk .fluentform .ff-el-input--label label {
  font-size: 0.78rem; font-weight: 700; color: var(--ink-soft);
  margin-bottom: 6px;
}

.sk .fluentform .ff-el-form-control {
  width: 100%;
  padding: 11px 13px;
  border-radius: 9px;
  border: 1.4px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
}
.sk .fluentform .ff-el-form-control:focus {
  outline: 2px solid var(--aircon);
  outline-offset: 1px;
  border-color: var(--aircon);
}

/*
   The submit button is NAVY, not the action red-orange.

   Spec §10 reserves the action colour for call buttons and nothing else, and §9
   ranks the form third behind call and WhatsApp. A form submit dressed as a call
   button would compete with the real one sitting beside it.
*/
.sk .fluentform .ff-btn-submit {
  background: var(--navy);
  color: var(--on-navy);
  border: 0;
  border-radius: 10px;
  padding: 13px 22px;
  min-height: 48px;
  font-weight: 700;
  font-size: 0.95rem;
}
.sk .fluentform .ff-btn-submit:hover { background: var(--navy-2); color: var(--on-navy); }

.sk .fluentform .ff-el-is-error .ff-el-form-control { border-color: var(--action); }
.sk .fluentform .error-text, .sk .fluentform .text-danger { color: var(--action); font-size: 0.8rem; }

/* ==========================================================================
   ASTRA CONTENT WRAPPER

   This theme renders edge-to-edge bands (navy page hero, stats band, closing
   call band) and manages inner width itself with .rr-container. Astra wraps the
   whole of #content in `.ast-container` at max-width:1280px with auto margins,
   which inset every band and left pale gutters down both sides.

   20-theme.sh sets Astra's content layout to 'page-builder' (Full Width /
   Stretched), which is the correct configuration intent — but it does not remove
   this wrapper on its own, so the constraint is cleared here explicitly. The
   selector is specific enough to beat Astra's own rules without !important.
   ========================================================================== */
.sk #content > .ast-container {
  max-width: none;
  width: 100%;
  /* All four sides: Astra's 20px vertical padding showed as a pale strip between
     the last section and the footer, since our bands supply their own spacing. */
  padding: 0;
  margin-left: 0;
  margin-right: 0;

  /* Astra sets this to flex to place a sidebar beside the content. There are no
     sidebars on this site (20-theme.sh sets no-sidebar everywhere), and as a flex
     item our <main> sized to its content instead of filling — leaving the bands
     stopping short at roughly 58% of the viewport. Block layout is what a
     single-column, full-width page actually wants. */
  display: block;
}
.sk #content > .ast-container > main { width: 100%; }

/* ==========================================================================
   INNER PAGES
   ========================================================================== */

/*
   Page hero.

   theme.json sets headings to brand navy, which would be navy-on-navy inside
   these bands — every dark band therefore restates its heading colour.
*/
.rr-pagehero {
  background: var(--navy); color: var(--on-navy);
  padding: 44px 0 52px;
  border-bottom: 3px solid var(--navy-2);
}
.rr-pagehero h1 { color: var(--on-navy); font-size: 2.4rem; margin: 0; }
.rr-pagehero__lede { color: var(--on-navy-soft); font-size: 1.02rem; max-width: 58ch; margin: 14px 0 0; }

/* the service line the page belongs to, as a coloured rule and label — colour as
   wayfinding, per spec §10 */
.rr-pagehero--elec  { border-bottom-color: var(--electrical); }
.rr-pagehero--plumb { border-bottom-color: var(--plumbing); }
.rr-pagehero--air   { border-bottom-color: var(--aircon); }

.rr-pagehero__line {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  margin-bottom: 10px;
}
.rr-pagehero__line .rr-icon { width: 15px; height: 15px; }
.rr-pagehero--elec  .rr-pagehero__line { color: var(--electrical); }
.rr-pagehero--plumb .rr-pagehero__line { color: var(--plumbing); }
.rr-pagehero--air   .rr-pagehero__line { color: var(--aircon); }

.rr-crumb { display: flex; flex-wrap: wrap; gap: 8px; font-size: 0.78rem; color: var(--on-navy-soft); margin-bottom: 14px; }
.rr-crumb a:hover { color: var(--on-navy); text-decoration: underline; }

/* page body copy */
.rr-prose { max-width: 68ch; }
.rr-prose p { margin: 0 0 1.1em; }
.rr-prose h2 { font-size: 1.5rem; margin: 1.6em 0 0.5em; }
.rr-prose h3 { font-size: 1.15rem; margin: 1.4em 0 0.4em; }
.rr-prose ul, .rr-prose ol { margin: 0 0 1.1em 1.2em; }
.rr-prose li { margin-bottom: 0.4em; }

/* child service list on hub pages */
.rr-services { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.rr-service {
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 12px; padding: 18px 20px;
  display: flex; flex-direction: column; gap: 8px;
}
.rr-service h3 { font-size: 1rem; margin: 0; }
.rr-service--elec  { border-left-color: var(--electrical); }
.rr-service--plumb { border-left-color: var(--plumbing); }
.rr-service--air   { border-left-color: var(--aircon); }
.rr-service__go { font-size: 0.82rem; font-weight: 700; display: inline-flex; align-items: center; gap: 5px; color: var(--ink-soft); }
.rr-service__go .rr-icon { width: 14px; height: 14px; transform: rotate(-90deg); }
.rr-service:hover .rr-service__go { color: var(--ink); }

/*
   A service page that is still a draft renders as plain text, not a link — a
   draft 404s for a logged-out visitor. This marks it as "call us" rather than
   dressing it up as a page that exists. See rr_block_child_services().
*/
.rr-service.is-pending { background: var(--surface-alt); }
.rr-service__pending { font-size: 0.78rem; color: var(--ink-soft); }

/* closing call band — spec §9: service pages end in a call, never a form */
.rr-callband { background: var(--navy); color: var(--on-navy); padding: 54px 0; }
.rr-callband__inner { display: flex; justify-content: space-between; align-items: center; gap: 30px; flex-wrap: wrap; }
.rr-callband h2 { color: var(--on-navy); font-size: 1.8rem; }
.rr-callband p { color: var(--on-navy-soft); margin: 8px 0 0; max-width: 48ch; }
.rr-callband__actions { display: flex; gap: 12px; flex-wrap: wrap; }
/* the outlined WhatsApp needs the bright brand green to stay legible on navy */
.sk .rr-callband .rr-btn--wa { color: var(--wa); border-color: var(--wa); }

.rr-map__inner {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  color: var(--ink-soft); font-size: 0.82rem;
}

/* ==========================================================================
   PERSISTENT CTAs — spec §4

   Reachable from any scroll position on every page. Desktop gets a floating
   WhatsApp bubble; mobile gets a fixed half-and-half bottom bar.
   ========================================================================== */
.rr-wa-float {
  position: fixed; right: 26px; bottom: 26px; z-index: 30;
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--wa); color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 14px 30px -10px rgb(0 0 0 / 45%);
}
.rr-wa-float .rr-icon { width: 26px; height: 26px; }
.rr-wa-float:hover { background: #1fba59; }

/*
   Astra's scroll-to-top control.

   It anchors bottom-right — the same corner as the WhatsApp bubble on desktop
   and the fixed call bar on mobile — and appeared as a stray blue arrow sitting
   on top of the WhatsApp action.

   It is hidden rather than disabled in Astra's settings: with the setting off,
   Astra removes the markup but frontend.min.js still runs its handler and throws
   a TypeError on every page load. Keeping the element and hiding it leaves the
   console clean, and display:none also takes it out of the tab order.

   !important is required because Astra's own script writes inline display
   styles onto this element as the page scrolls.
*/
#ast-scroll-top { display: none !important; }

/* Back-to-top control removed at the owner's request 2026-08-17 — it crowded
   the WhatsApp bubble in the same corner. */

.rr-mobilebar { display: none; }

/* ==========================================================================
   MOBILE  (< 782px — matches Astra and WordPress core, so no custom breakpoint
   logic is introduced. Spec §4.)

   Mobile is a designed layout, not the desktop one reflowed: elements are
   dropped, stacking order changes, and the testimonials become a scroller.
   ========================================================================== */
@media (max-width: 781px) {
  .rr-container { padding: 0 20px; }
  .rr-section { padding: 52px 0; }
  .sk h2.display { font-size: 1.55rem; }

  .rr-callstrip {
    display: flex; align-items: center; justify-content: center; gap: 7px;
    background: var(--action); color: var(--on-action);
    padding: 9px 12px; font-size: 0.8rem; font-weight: 700;
  }
  .rr-callstrip .rr-icon { width: 15px; height: 15px; }
  .rr-callstrip .sep { opacity: 0.55; }

  .rr-header__row { gap: 12px; padding: 10px 0; }
  .rr-brand { margin-right: auto; }
  .rr-brand img, .rr-brand svg { height: 30px; }
  /* Scoped to the header ROW, not .rr-header — the drawer is a child of the
     header, and the looser selector was hiding the drawer's own Call button too.
     The row's call button is redundant on mobile because the call strip above and
     the fixed bar below both carry it; the drawer's is not. */
  .rr-header__row .rr-btn--call { display: none; }
  .rr-nav { display: none; }
  .rr-burger { display: flex; }

  .rr-hero { padding: 44px 0 40px; }
  .rr-hero__grid { grid-template-columns: 1fr; gap: 28px; }
  .rr-hero h1 { font-size: 2.05rem; }
  .rr-hero__photo { height: 210px; transform: none; }
  .rr-hero__photo.has-img { box-shadow: 8px 8px 0 -2px var(--electrical-tint), var(--shadow); }
  /* on a phone the technician sits behind the text, so the scrim carries more */
  .rr-hero.has-bg { padding: 64px 0 56px; background-position: 68% center; }
  .rr-hero.has-bg::after { background: rgb(7 24 46 / 86%); }
  .rr-card__media { height: 150px; }

  .rr-triad { grid-template-columns: 1fr; }
  .rr-triad .rr-card { transform: none !important; }

  .rr-split { grid-template-columns: 1fr; }
  .rr-callcard { position: static; }

  .rr-about { grid-template-columns: 1fr; }
  .rr-about__photo { height: 190px; }

  .rr-feat { column-count: 1; }

  .rr-stats__grid { grid-template-columns: 1fr 1fr; text-align: left; }
  .rr-stat__n { font-size: 1.5rem; }

  .rr-process { grid-template-columns: 1fr; gap: 22px; }
  .rr-process::before { display: none; }

  .rr-pkgs { grid-template-columns: 1fr; }

  /* horizontal scroller rather than three stacked cards */
  .rr-testi {
    grid-template-columns: none;
    grid-auto-flow: column; grid-auto-columns: 86%;
    overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 6px;
  }
  .rr-testi .rr-card { scroll-snap-align: start; }

  .rr-contact { grid-template-columns: 1fr; }

  .rr-pagehero { padding: 30px 0 34px; }
  .rr-pagehero h1 { font-size: 1.7rem; }
  .rr-services { grid-template-columns: 1fr; }
  .rr-callband { padding: 40px 0; }
  .rr-callband h2 { font-size: 1.45rem; }
  /* Stacked, not side by side: at 390px two flexed buttons are narrow enough
     that "+65 8393 8582" breaks across two lines. A phone number that wraps
     reads as two numbers. */
  .rr-callband__actions { width: 100%; flex-direction: column; }
  .rr-callband__actions .rr-btn { width: 100%; }

  .rr-footer__grid { grid-template-columns: 1fr 1fr; gap: 26px 20px; }
  /* the contact column carries a long email and address, so it gets a full row
     rather than being squeezed into a half column and clipped */
  .rr-footer__grid > :first-child,
  .rr-footer__grid > :last-child { grid-column: 1 / -1; }

  .rr-wa-float { display: none; }

  /* clears the fixed call bar rather than sitting on top of it */

  .rr-mobilebar {
    position: fixed; inset: auto 0 0 0; z-index: 30;
    display: flex;
    border-top: 1px solid var(--border);
    background: var(--surface);
    box-shadow: 0 -8px 22px -12px rgb(15 26 34 / 35%);

    /* Height is pinned and border-box so the bar measures EXACTLY --rr-bar-h.
       Without this the 1px border-top is added on top of the children's
       min-height, the bar renders 1px taller than the padding the body reserves,
       and it clips the last line of the footer. Spec §4 requires the reservation
       to match, so the height is made deterministic rather than the number
       fudged. */
    height: var(--rr-bar-h);
    box-sizing: border-box;
  }
  .rr-mobilebar a {
    flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
    height: 100%;              /* 57px of tap target — still well over the 48px floor */
    font-weight: 700; font-size: 0.9rem;
  }
  .rr-mobilebar .is-call { background: var(--action); color: var(--on-action); flex: 1.2; }
  .rr-mobilebar .is-call .rr-icon {
    width: 24px; height: 24px; padding: 5px; box-sizing: border-box;
    border-radius: 50%; background: rgb(255 255 255 / 94%); color: var(--action); flex: none;
  }
  .rr-mobilebar .is-wa { color: var(--wa-ink); }
  .rr-mobilebar .rr-icon { width: 19px; height: 19px; }

  /* The bar is fixed, so the page reserves matching bottom padding. Without this
     it covers the footer and the last field of the quote form. Spec §4. */
  body.sk { padding-bottom: var(--rr-bar-h); }
}

@media (prefers-reduced-motion: no-preference) {
  .rr-card, .rr-btn, .rr-nav .sub-menu { transition: background-color 0.15s, transform 0.15s, box-shadow 0.15s, opacity 0.12s; }
}

/* ------------------------------------------------------------------ */
/* Lead image prepended to the three pillar pages (stock photos,       */
/* placed 2026-08-14). Capped height so portrait crops don't dominate. */
/* ------------------------------------------------------------------ */

.rr-page-lead-img img {
	width: 100%;
	max-height: 420px;
	object-fit: cover;
	border-radius: 14px;
}

/* ------------------------------------------------------------------ */
/* Licences & registrations (About page, 2026-08-17). Certificate      */
/* image sits in a white matte like the hero photos; text credentials  */
/* read as cards from the same system.                                 */
/* ------------------------------------------------------------------ */

.rr-creds { margin-top: 56px; }
.rr-cred-img img {
	width: 100%;
	border: 6px solid #fff;
	outline: 1.5px solid var(--border);
	border-radius: 10px;
	box-shadow: var(--shadow-lift);
}
.rr-cred-cap { font-size: 0.85rem; color: var(--ink-soft); margin-top: 10px; }
.rr-cred-card {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	padding: 22px 24px;
	margin-bottom: 18px;
	box-shadow: var(--shadow);
	position: relative;
	overflow: hidden;
}
.rr-cred-card::before {
	content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
	background: var(--busbar);
}
.rr-cred-card h3 { margin-top: 0; font-size: 1.05rem; }
.rr-cred-card p { font-size: 0.92rem; margin-bottom: 0.6em; }
