/* =============================================================
   brand-overrides.css — patch layer over the built Vite bundle.

   This folder is a build artifact with no source repo on this
   machine, so these changes live here as an override sheet
   loaded AFTER index-*.css. Port each block into the real
   source before the next `vite build`, or it is lost.

   1. Type      — Poppins (matches smart-tech.melbourne)
   2. Colour    — brand red #e40d13 (from smart-tech.melbourne)
   3. Logo      — 34px was too small
   4. Scale     — hero was smaller than section titles
   5. Spacing   — section padding cut ~40%
   ============================================================= */

/* --- 1 + 2. tokens ------------------------------------------ */
/* Everything in the bundle reads these vars, so overriding the
   four of them re-skins the whole site. */
:root {
  /* Header height tracks the logo, so the hero offset is derived from
     it rather than a magic number — bump the logo and spacing follows. */
  --logo-h: clamp(42px, 4.2vw, 58px);
  /* .header is position:fixed — logo + its 1.25rem top/bottom padding. */
  --header-h: calc(var(--logo-h) + 2.5rem);
  /* Switzer — a neutral modern grotesk. Four faces have been tried:
     Helvetica Now (original), Poppins and Plus Jakarta Sans (geometric),
     and Clash Display (high personality). All were rejected, so this goes
     the untried direction: restraint. Swiss-style, quiet, highly legible;
     it reads expensive through proportion rather than character.
     Swap these two lines plus the <link> in index.html to try another. */
  /* Clash Display for headings, Satoshi for body — the closest free
     equivalent to controleur.ca's Urbane pairing. Loaded from Fontshare
     (verified reachable) rather than Google Fonts. */
  --font-primary: "Switzer", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-display: "Switzer", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --accent: #e40d13;
  --accent-hover: #ff2d33;
}

/* --- 3. logo ------------------------------------------------- */
/* Was height:34px desktop / 28px mobile. One clamp replaces both. */
.header__logo-img { height: var(--logo-h) !important; }
.header__logo-text { font-size: clamp(1.15rem, 1.5vw, 1.4rem) !important; }

/* --- 4. type scale ------------------------------------------- */
/* Hero title capped at 3rem while .svc__title went to 5rem —
   the hero read as the smaller heading. Bring it up. */
.hero__title  { font-size: clamp(2.4rem, 5.2vw, 4.5rem) !important;
                letter-spacing: -.035em !important; }
.hero__lead   { font-size: clamp(1rem, 1.15vw, 1.15rem) !important;
                line-height: 1.65 !important; }
.svc__desc,
.approach__desc,
.whysmart__desc { font-size: clamp(1rem, 1.1vw, 1.1rem) !important;
                  line-height: 1.7 !important; }
.hero__cta    { font-size: 1rem !important; }

/* Display headings: tighter tracking, Poppins runs wide. */
.svc__title, .approach__title, .whatwedo__text, .hero__title {
  letter-spacing: -.035em !important;
}

/* --- 5. spacing ---------------------------------------------- */
/* Each of these had 3 separate media-query values; a clamp
   collapses all three into one responsive rule.
   NOTE: min-height:100vh is deliberately left alone on the
   pinned sections (.whatwedo, .approach, .whysmart) — GSAP
   ScrollTrigger pins them and needs exactly one viewport. */
/* padding-top must clear the fixed header (logo + its 1.25rem padding). */
.hero      { padding: calc(var(--header-h) + 0.75rem) clamp(1.25rem, 3vw, 3rem)
                      clamp(2rem, 4vw, 3.5rem) !important; }
/* .whatwedo and .whysmart are pinned at `top top`, so they sit under the
   fixed header for their whole pin — their first line needs to clear it. */
.whatwedo  { padding: calc(var(--header-h) + 0.5rem) clamp(1rem, 3vw, 2.5rem)
                      1.25rem !important; }
.whysmart  { padding-top: calc(var(--header-h) + 0.5rem) !important; }
.svc       { padding: clamp(2.5rem, 4.5vw, 3.5rem) clamp(1rem, 3vw, 2.5rem) !important;
             min-height: auto !important; }   /* not pinned — safe to collapse */
.approach  { padding: clamp(2rem, 3.5vw, 3rem) clamp(1rem, 3vw, 2.5rem) !important; }
.products-panel__inner { padding: clamp(1.5rem, 3vw, 2.5rem)
                                  clamp(1.25rem, 3.5vw, 3rem) !important; }
.footer    { padding: clamp(2.5rem, 4vw, 3rem) clamp(1.25rem, 3vw, 2.5rem) 0 !important; }


/* --- 6. display weight -------------------------------------- */
/* The reference sets headings at 600 with ~-0.015em tracking; the build
   left everything at 400, which looks thin in a geometric face. */
.hero__title, .svc__title, .approach__title, .whatwedo__text,
.whysmart__title, .products-panel__title {
  font-weight: 600 !important;
  letter-spacing: -.028em !important;
}

/* --- 7. service cards --------------------------------------- */
/* Was a clip-path chamfer plus a hard drop shadow, which read as a
   detached square floating over the globe. Rounded corners, a hairline
   gradient edge and a soft red glow sit the card on the background
   instead of on top of it. */
.svc__card-inner {
  clip-path: none !important;
  border-radius: 16px !important;
  border: 1px solid rgba(255, 255, 255, .09) !important;
  background: linear-gradient(150deg, rgba(28,28,32,.82), rgba(10,10,12,.72)) !important;
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(14px) saturate(1.15);
  box-shadow: 0 18px 50px rgba(0,0,0,.45),
              inset 0 1px 0 rgba(255,255,255,.06) !important;
  transition: transform .45s cubic-bezier(.22,1,.36,1),
              border-color .45s, box-shadow .45s !important;
}
/* The two glowing hairlines belonged to the chamfer — they now read as
   stray marks on a rounded card. */
.svc__card-inner:before, .svc__card-inner:after { display: none !important; }

.svc__card:hover .svc__card-inner {
  transform: translateY(-6px) !important;
  border-color: rgba(228, 13, 19, .55) !important;
  box-shadow: 0 26px 60px rgba(0,0,0,.55),
              0 0 34px rgba(228, 13, 19, .18),
              inset 0 1px 0 rgba(255,255,255,.09) !important;
}

/* --- 8. footer ----------------------------------------------- */
/* The full-width SMART-TECH® wordmark slab (15.3vw) is removed —
   requested, and it was the tallest thing on the page after the pins. */
.footer__wordmark-wrap { display: none !important; }

/* --- 9. contact form ----------------------------------------- */
/* Two problems here. The section carried a second accent (#2563eb /
   #1d4ed8 / #3b82f6) that fought the brand red, and the controls used
   four different radii — inputs at 999px pills, textarea 20px, info
   tiles 14px, icons 12px — so nothing lined up. One token fixes the
   shape, brand red replaces the blue.
   White on #e40d13 measures 4.81:1, so it clears WCAG AA for the
   button label. */
:root { --field-radius: 14px; }

.cform__input,
.cform__textarea,
.cform__submit,
.cform__info-item { border-radius: var(--field-radius) !important; }
.cform__info-icon,
.cform__msg       { border-radius: calc(var(--field-radius) - 3px) !important; }

.cform__info-icon { background: var(--accent) !important; }

.cform__input:focus {
  background: rgba(228, 13, 19, .06) !important;
  border-color: rgba(228, 13, 19, .6) !important;
  /* the build removed the outline; put a visible focus ring back */
  box-shadow: 0 0 0 3px rgba(228, 13, 19, .18) !important;
}

.cform__submit        { background: var(--accent) !important; font-weight: 600 !important; }
.cform__submit:hover  { background: var(--accent-hover) !important; }

/* Lone blue glyph in the footer heading. */
.footer__intro-mark { color: var(--accent) !important; }

/* --- 10. route pages: CTAs -----------------------------------
   The service / product / blog route chunks carry their own copy of the
   old blue accent (#2563eb, #1d4ed8, #3b82f6). Their stylesheets are
   injected on route load, i.e. AFTER this file, so these need
   !important to win.

   Deliberately NOT touched: .fsplit__card-icon--blue and
   .fsplit__card-action--blue, which are explicit colour variants sitting
   next to --green ones. Those are design, not a stray brand accent. */
.svc-hero__btn--primary,
.product-cta__btn--primary,
.vgrid__cta,
.blog__cta,
.blog-admin__submit           { background: var(--accent) !important; }
.svc-hero__btn--primary:hover,
.product-cta__btn--primary:hover,
.vgrid__cta:hover,
.blog__cta:hover              { background: var(--accent-hover) !important; }

.svc-hero__stat-bar           { border-bottom-color: var(--accent) !important; }
.vgrid__card:hover            { border-color: rgba(228, 13, 19, .5) !important; }

/* Gradient wordmark accent — was blue→indigo. */
.vgrid__title-accent {
  background: linear-gradient(90deg, #ff6a6f 0%, var(--accent) 55%, #8e0509 100%) !important;
  -webkit-background-clip: text !important;
  background-clip: text !important;
}

/* Product-features block on the service pages. */
.pfeat__cta        { background: #2a0406 !important;
                     border-color: rgba(228,13,19,.45) !important; }
.pfeat__cta:hover  { background: #3a0508 !important; }
.pfeat__check      { background: var(--accent) !important; }

/* --- 11. "One Technology Partner" section --------------------
   .whatwedo__works was pinned to the bottom with margin-top:auto while
   the copy sat at the top, opening a ~309px hole in the middle of a
   100vh pinned section. Centring the group spreads that slack to the
   edges instead of pooling it between the sentence and the strip. */
.whatwedo__inner { justify-content: center !important; gap: clamp(1.5rem, 3vw, 2.75rem); }
.whatwedo__works { margin-top: 0 !important; }
.whatwedo__text  { margin-bottom: 0 !important; }
.whatwedo__label { margin-bottom: 0 !important; }

/* The wipe reads better with a touch more line spacing. */
.whatwedo__text { line-height: 1.28 !important; }

/* Base state for the wipe. The bundle CSS sets opacity:0, so any word the
   timeline has not reached is fully invisible and the sentence appears to
   stop mid-way. .14 matches the tween's "from" value. Deliberately NOT
   !important — GSAP writes inline styles and must still win. */
.whatwedo__word { opacity: .14; }

/* --- 13. approach cards: glass + neon hover ------------------
   These were flat #000 boxes with a hairline border, which read as
   empty rectangles. Now frosted glass with a neon edge on hover.

   IMPORTANT: these are 3D flip cards — GSAP animates rotateY on
   .approach-card__inner as you scroll. Nothing here may set `transform`
   on the card or its inner, or it fights the flip. The hover effect is
   therefore built purely from colour, border, shadow and opacity. */
.approach-card__face {
  background:
    linear-gradient(160deg, rgba(255,255,255,.075), rgba(255,255,255,.02) 42%, rgba(0,0,0,.28)),
    rgba(14,14,17,.72) !important;
  border: 1px solid rgba(255,255,255,.14) !important;
  box-shadow:
    0 18px 46px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -1px 0 rgba(255,255,255,.04) !important;
  transition: border-color .4s ease, box-shadow .4s ease, background .4s ease;
}

/* Neon ring. A pseudo-element so the glow can fade independently of the
   card's own background, and so it costs nothing until hovered. */
.approach-card__face::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .4s ease;
  box-shadow:
    inset 0 0 0 1px rgba(228,13,19,.85),
    inset 0 0 22px rgba(228,13,19,.30),
    0 0 26px rgba(228,13,19,.34);
}

.approach-card:hover .approach-card__face {
  border-color: rgba(228,13,19,.55) !important;
  box-shadow:
    0 26px 60px rgba(0,0,0,.6),
    0 0 34px rgba(228,13,19,.20),
    inset 0 1px 0 rgba(255,255,255,.16) !important;
}
.approach-card:hover .approach-card__face::after { opacity: 1; }

/* Icon picks up the neon too. */
.approach-card__icon { transition: filter .4s ease, opacity .4s ease; }
.approach-card:hover .approach-card__icon {
  filter: drop-shadow(0 0 9px rgba(228,13,19,.75));
}

@media (prefers-reduced-motion: reduce) {
  .approach-card__face,
  .approach-card__face::after,
  .approach-card__icon { transition: none; }
}

/* --- 14. "One Technology Partner" — two-column with image -----
   Was a single full-width paragraph above the works strip, which read
   as a flat wall of text. Now the statement sits in a left column with
   a supporting image beside it, works strip full-width underneath.

   The image is a grid item made from ::before, because the section's
   DOM cannot be changed from here. */
.whatwedo__inner {
  display: grid !important;
  /* image left, copy right */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  grid-template-rows: auto auto auto;
  column-gap: clamp(1.5rem, 3vw, 3.25rem);
  row-gap: clamp(1rem, 2vw, 1.75rem);
  align-content: center;
}
.whatwedo__label { grid-column: 2; grid-row: 1; }
.whatwedo__text  { grid-column: 2; grid-row: 2; }
.whatwedo__works { grid-column: 1 / -1; grid-row: 3; }

.whatwedo__inner::before {
  content: "";
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  min-height: clamp(240px, 27vw, 430px);
  /* Purpose-made 3D isometric render: near-black ground, brand-red glowing
     links between a data core, cloud, shield, laptop, router and IoT nodes.
     Replaces a photo of the word "Security", which was both too literal and
     text-inside-an-image. 4.6MB PNG re-encoded to a 119KB progressive JPEG. */
  background: url("/service/capabilities-iso.jpg") center / contain no-repeat;
  box-shadow: none;
  /* Slow drift so the render feels alive without competing with the
     scroll-linked text wipe beside it. Transform only — nothing here is
     GSAP-driven, so this cannot fight a tween. */
  animation: iso-float 9s ease-in-out infinite;
  will-change: transform;
  /* The render ships on charcoal, not pure black, so it still read as a
     rectangle against the page. mix-blend-mode:screen made it worse (screen
     lightens, so the charcoal became a brighter grey box). Feathering the
     edges to transparent instead dissolves the boundary whatever the
     image background happens to be. */
  -webkit-mask-image: radial-gradient(ellipse 68% 64% at 50% 48%, #000 26%, transparent 78%);
          mask-image: radial-gradient(ellipse 68% 64% at 50% 48%, #000 26%, transparent 78%);
}

/* One column on smaller screens — the statement matters more than the art. */
@media (max-width: 900px) {
  /* minmax(0,1fr), not 1fr: a bare 1fr is minmax(auto,1fr) and refuses to
     shrink below the text's min-content width, which blew the column out to
     1347px on a 390px screen. */
  .whatwedo__inner { grid-template-columns: minmax(0, 1fr); }
  .whatwedo__inner::before { display: none; }
  .whatwedo__label, .whatwedo__text, .whatwedo__works { grid-column: 1; }
}

/* Each word is its own inline-block with only a margin between them, so
   the sentence copies and reads out as "Fromday-to-dayITsupport...".
   A real space in ::after restores word boundaries for copy/paste and
   screen readers; margin-right goes to 0 so spacing does not double. */
.whatwedo__word { margin-right: 0 !important; }
.whatwedo__word::after { content: " "; white-space: pre; }

/* --- 15. approach cards: a photo per step --------------------
   The front faces showed only a small line icon on black. Each step now
   carries a photograph, under a vertical scrim dark enough to keep the
   number, icon and label legible over any part of the image.

   These four are also in the RECENT WORKS strip, but that sits in a
   different pinned section, so the two are never on screen together. */
.approach-card .approach-card__front {
  background-position: center !important;
  background-size: cover !important;
  background-repeat: no-repeat !important;
}
.approach-card:nth-child(1) .approach-card__front {
  background-image:
    linear-gradient(180deg, rgba(8,8,10,.80), rgba(8,8,10,.62) 26%, rgba(8,8,10,.76) 60%, rgba(8,8,10,.94)),
    url("/product/gallery-ai-tracker.jpg") !important;
}
.approach-card:nth-child(2) .approach-card__front {
  background-image:
    linear-gradient(180deg, rgba(8,8,10,.80), rgba(8,8,10,.62) 26%, rgba(8,8,10,.76) 60%, rgba(8,8,10,.94)),
    url("/product/gallery-aquapilot.jpg") !important;
}
.approach-card:nth-child(3) .approach-card__front {
  background-image:
    linear-gradient(180deg, rgba(8,8,10,.80), rgba(8,8,10,.62) 26%, rgba(8,8,10,.76) 60%, rgba(8,8,10,.94)),
    url("/product/gallery-postie.jpg") !important;
}
.approach-card:nth-child(4) .approach-card__front {
  background-image:
    linear-gradient(180deg, rgba(8,8,10,.80), rgba(8,8,10,.62) 26%, rgba(8,8,10,.76) 60%, rgba(8,8,10,.94)),
    url("/product/gallery-connected.jpg") !important;
}

/* Lift the scrim slightly on hover so the photo reads through. */
.approach-card:hover .approach-card__front {
  background-image:
    linear-gradient(180deg, rgba(8,8,10,.70), rgba(8,8,10,.46) 26%, rgba(8,8,10,.62) 60%, rgba(8,8,10,.88)),
    var(--card-img) !important;
}
.approach-card:nth-child(1):hover .approach-card__front { --card-img: url("/product/gallery-ai-tracker.jpg"); }
.approach-card:nth-child(2):hover .approach-card__front { --card-img: url("/product/gallery-aquapilot.jpg"); }
.approach-card:nth-child(3):hover .approach-card__front { --card-img: url("/product/gallery-postie.jpg"); }
.approach-card:nth-child(4):hover .approach-card__front { --card-img: url("/product/gallery-connected.jpg"); }

/* Icon and label need to hold up against a photo now, not flat black. */
.approach-card__icon  { filter: drop-shadow(0 2px 6px rgba(0,0,0,.85)); }
.approach-card__num,
.approach-card__label { text-shadow: 0 1px 6px rgba(0,0,0,.9); }

/* =============================================================
   16. Site-wide glass + neon system
   -------------------------------------------------------------
   One set of tokens drives every panel, card and image frame so
   the whole site reads as one material instead of a dozen
   one-off treatments.

   Rules that shaped this:
   - No `transform` in any hover. Several of these surfaces are
     animated by GSAP (3D flips, horizontal scroll strips); a
     hover transform fights the tween and makes them jump.
   - No backdrop-filter on anything inside a preserve-3d context
     — it renders inconsistently there.
   - .products-panel is left alone: it has per-product brand
     colours that are meant to differ.
   ============================================================= */
:root {
  --glass-bg: linear-gradient(158deg, rgba(255,255,255,.075), rgba(255,255,255,.022) 44%, rgba(0,0,0,.26));
  --glass-tint: rgba(16,16,19,.62);
  --glass-border: rgba(255,255,255,.12);
  --glass-shadow: 0 18px 46px rgba(0,0,0,.5);
  --glass-inset: inset 0 1px 0 rgba(255,255,255,.13), inset 0 -1px 0 rgba(255,255,255,.035);
  --neon: rgba(228,13,19,.6);
  --neon-glow: 0 0 30px rgba(228,13,19,.22);
  --neon-ring: inset 0 0 0 1px rgba(228,13,19,.8), inset 0 0 20px rgba(228,13,19,.22);
}

/* --- glass surfaces ----------------------------------------- */
.whysmart__card-inner,
.cform__inner,
.cform__info-item,
.blog__card,
.vgrid__card,
.pfeat__item,
.about-hero__strip-item {
  background: var(--glass-bg), var(--glass-tint) !important;
  border: 1px solid var(--glass-border) !important;
  box-shadow: var(--glass-shadow), var(--glass-inset) !important;
  -webkit-backdrop-filter: blur(12px) saturate(1.1);
  backdrop-filter: blur(12px) saturate(1.1);
  transition: border-color .4s ease, box-shadow .4s ease;
}

/* Form fields: same material, lighter so they still read as inputs. */
.cform__input, .cform__textarea, .footer__input {
  background: linear-gradient(160deg, rgba(255,255,255,.06), rgba(255,255,255,.02)) !important;
  border: 1px solid rgba(255,255,255,.16) !important;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* --- glass image frames ------------------------------------- */
/* Images get the same edge treatment so photos sit in the system
   rather than floating as raw rectangles. */
.whatwedo__works-card,
.blog__card-thumb,
.vgrid__card-art,
.fsplit__visual,
.products-panel__visual {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--glass-shadow) !important;
}
.whatwedo__works-card::after,
.blog__card-thumb::after,
.vgrid__card-art::after,
.fsplit__visual::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.16),
              inset 0 1px 0 rgba(255,255,255,.14);
  background: linear-gradient(158deg, rgba(255,255,255,.10), rgba(255,255,255,0) 38%);
}

/* --- neon hover --------------------------------------------- */
.whysmart__card-inner:hover,
.blog__card:hover,
.vgrid__card:hover,
.pfeat__item:hover,
.cform__info-item:hover {
  border-color: var(--neon) !important;
  box-shadow: var(--glass-shadow), var(--neon-glow), var(--glass-inset) !important;
}
.whatwedo__works-card:hover::after,
.blog__card:hover .blog__card-thumb::after,
.vgrid__card:hover .vgrid__card-art::after {
  box-shadow: var(--neon-ring);
}

@media (prefers-reduced-motion: reduce) {
  .whysmart__card-inner, .cform__inner, .cform__info-item, .blog__card,
  .vgrid__card, .pfeat__item, .about-hero__strip-item { transition: none; }
}

/* --- 17. works strip: uniform cards --------------------------
   Cards were all 300px wide but took their height from each image
   (340/260/300/280/320/270), and the grid is align-items:flex-end,
   so the tops staggered. A fixed square ratio on the card plus a
   filling image makes all six identical. 1/1 sits inside the old
   height range, so the strip does not grow. */
.whatwedo__works-grid { align-items: stretch !important; }

.whatwedo__works-card {
  aspect-ratio: 1 / 1 !important;
  height: auto !important;
}
.whatwedo__works-card > img {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
  display: block;
}

/* --- 18. approach card icons ---------------------------------
   The shipped icons are 80x80 SVGs drawn with stroke="#666" at
   stroke-width 0.8 — hairline mid-grey, which all but vanishes now
   that each card sits on a photograph.

   Rather than edit four inline SVGs inside the bundle, the original
   is hidden and a replacement is drawn as a CSS mask, so the glyph
   takes its colour from background-color and inherits the existing
   hover glow. One coherent set, 1.75 stroke, round caps. */
.approach-card__icon > svg { display: none !important; }

.approach-card__icon {
  background-color: #fff;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: 46px 46px;   mask-size: 46px 46px;
}

/* 01 Understand — magnifier over a bar chart (analysis) */
.approach-card:nth-child(1) .approach-card__icon {
  -webkit-mask-image: var(--ic-1); mask-image: var(--ic-1);
}
/* 02 Design — stacked layers */
.approach-card:nth-child(2) .approach-card__icon {
  -webkit-mask-image: var(--ic-2); mask-image: var(--ic-2);
}
/* 03 Connect — linked nodes */
.approach-card:nth-child(3) .approach-card__icon {
  -webkit-mask-image: var(--ic-3); mask-image: var(--ic-3);
}
/* 04 Build — assembled cube */
.approach-card:nth-child(4) .approach-card__icon {
  -webkit-mask-image: var(--ic-4); mask-image: var(--ic-4);
}

:root {
  --ic-1: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='1.75'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='10.8'%20cy='10.8'%20r='7'/%3E%3Cpath%20d='M20.5%2020.5l-4.6-4.6'/%3E%3Cpath%20d='M8.3%2012.4v-1.9M10.8%2012.4v-4.1M13.3%2012.4v-2.9'/%3E%3C/svg%3E");
  --ic-2: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='1.75'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%202.6l9.2%205.1L12%2012.8%202.8%207.7%2012%202.6z'/%3E%3Cpath%20d='M2.8%2012.5L12%2017.6l9.2-5.1'/%3E%3Cpath%20d='M2.8%2017l9.2%205.1L21.2%2017'/%3E%3C/svg%3E");
  --ic-3: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='1.75'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='4.6'%20r='2.3'/%3E%3Ccircle%20cx='4.8'%20cy='18.4'%20r='2.3'/%3E%3Ccircle%20cx='19.2'%20cy='18.4'%20r='2.3'/%3E%3Cpath%20d='M10.7%206.7L6.1%2016.3M13.3%206.7l4.6%209.6M7.1%2018.4h9.8'/%3E%3C/svg%3E");
  --ic-4: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='1.75'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%202.7l8.3%204.8v9.6L12%2021.9l-8.3-4.8V7.5L12%202.7z'/%3E%3Cpath%20d='M3.7%207.5L12%2012.3l8.3-4.8'/%3E%3Cpath%20d='M12%2012.3v9.6'/%3E%3C/svg%3E");
}

@keyframes iso-float {
  0%   { transform: translate3d(0, 0, 0)      scale(1);     }
  50%  { transform: translate3d(0, -14px, 0)  scale(1.018); }
  100% { transform: translate3d(0, 0, 0)      scale(1);     }
}
@media (prefers-reduced-motion: reduce) {
  .whatwedo__inner::before { animation: none; }
}


/* --- 19. works strip fits short viewports --------------------
   .whatwedo is pinned at 100vh, so everything inside has to fit one
   screen. The cards are square, so their width sets their height —
   at 940px tall the 300px cards overflowed the bottom and appeared
   cut off mid-scroll. Capping the width by vh as well fixes it. */
.whatwedo__works-card {
  width: min(clamp(180px, 18vw, 300px), 26vh) !important;
}
/* Give the image a little less room on short screens too. */
.whatwedo__inner::before {
  min-height: clamp(200px, min(27vw, 32vh), 430px);
}

/* --- 20. footer: newsletter removed ---------------------------
   The "Stay in the Loop" signup (feature drops / release notes) is a
   product-company pattern that does not apply here, and was requested
   gone. The left column keeps a single company line instead of being
   left empty, matching the footer on smart-tech.melbourne.

   The GitHub link was dropped and Facebook/LinkedIn repointed at the
   real profiles in the bundle — all three were placeholder roots
   (https://github.com, https://facebook.com, https://linkedin.com). */
.footer__intro-desc,
.footer__form,
.footer__intro-mark { display: none !important; }

.footer__intro-title {
  font-size: clamp(1.05rem, 1.5vw, 1.4rem) !important;
  font-weight: 500 !important;
  line-height: 1.45 !important;
  max-width: 22ch;
  color: var(--text-secondary, #b9b9bf) !important;
}

/* --- 21. footer laid out like smart-tech.melbourne ------------
   Target structure: logo + line | Quick Links | Our Product |
   Contact Info (labelled), with a copyright rule underneath.

   The bundle renders ONE "Quick Links" heading above two <ul>s, and
   the contact values carry no field labels. Both gaps are filled with
   generated content rather than DOM surgery on a minified build. */

/* Logo above the company line. */
.footer__col-left { position: relative; }
.footer__intro-title::before {
  content: "";
  display: block;
  width: clamp(150px, 13vw, 190px);
  height: clamp(38px, 3.4vw, 50px);
  margin-bottom: 1.25rem;
  background: url("/smart-tech-logo-tm_White.png") left center / contain no-repeat;
}

/* Second list needs its own heading — the bundle only prints one. */
.footer__pages { position: relative; }
.footer__pages-list:nth-of-type(2)::before {
  content: "Our Product";
  display: block;
  margin-bottom: .9rem;
  font-family: var(--font-primary);
  font-size: .72rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-muted, #8a8a92);
}
/* Keep the two lists' first items aligned now that one has a heading. */
.footer__pages-list:nth-of-type(1) { padding-top: 0; }

/* Field labels on the contact rows, in the order the bundle renders them:
   email, phone, address. */
.footer__contact-block .footer__contact-link,
.footer__contact-block .footer__contact-line { display: block; margin-bottom: .85rem; }
.footer__contact-block .footer__contact-link::before,
.footer__contact-block .footer__contact-line::before {
  display: block;
  margin-bottom: .15rem;
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-muted, #8a8a92);
}
.footer__contact-block .footer__contact-link:nth-of-type(1)::before { content: "Email"; }
.footer__contact-block .footer__contact-link:nth-of-type(2)::before { content: "Hotline"; }
.footer__contact-block .footer__contact-line::before { content: "Address"; }

/* Copyright rule. .footer__wordmark-wrap is the last child and already
   hidden, so it is reused as the bar rather than adding an element. */
.footer__wordmark-wrap {
  display: block !important;
  /* .footer__grid already carries a border-bottom, so adding a border-top
     here drew a second rule with a gap between the two. Use the existing
     one and just sit beneath it. */
  padding: 1.25rem 0 2rem !important;
  margin-top: 0;
  border-top: 0;
  text-align: center;
}
.footer__wordmark { display: none !important; }
.footer__wordmark-wrap::after {
  content: "Copyright © 2026 Smart-Tech Enterprise Solutions Pty Ltd. All rights reserved.";
  display: block;
  font-family: var(--font-primary);
  font-size: .8rem;
  color: var(--text-muted, #8a8a92);
}

/* --- 23. product pages, closer to the AquaPilot layout --------
   Reference: smart-tech.melbourne/aquapilot — a dashed eyebrow, a big
   heading with body copy beside it, and a three-up grid of image cards.

   The DOM here cannot be extended, so this works with what exists:
   .pfeat__list was five full-width stacked rows; it becomes a three-up
   card grid, the check glyph becomes a corner badge, and the first three
   cards get a product image band. That is the reference layout's
   signature, achieved without new markup. */

/* Dashed eyebrow, as on the reference page. */
[data-product] .pfeat__eyebrow {
  display: inline-flex !important;
  align-items: center;
  gap: .7rem;
  background: none !important;
  border: 0 !important;
  padding: 0 !important;
  color: var(--accent) !important;
  letter-spacing: .16em;
}
[data-product] .pfeat__eyebrow::before {
  content: "";
  width: 34px;
  height: 2px;
  background: var(--accent);
  flex: none;
}

/* Copy above, cards below — the reference stacks them rather than
   putting the list in a side column. */
[data-product] .pfeat__inner {
  display: block !important;
}
[data-product] .pfeat__copy {
  max-width: 100%;
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}
[data-product] .pfeat__title {
  max-width: 22ch;
  font-size: clamp(1.8rem, 3.2vw, 2.9rem) !important;
  line-height: 1.15 !important;
}

/* Three-up card grid. */
[data-product] .pfeat__list {
  display: grid !important;
  /* Explicit 3-up: auto-fit gave four columns at 1920px, and the
     reference page is a three-up grid. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 1.8vw, 1.5rem);
  align-items: stretch;
}
[data-product] .pfeat__item {
  display: block !important;
  position: relative;
  padding: 0 0 1.4rem !important;
  overflow: hidden;
  border-radius: 16px;
}
[data-product] .pfeat__body { padding: 0 1.25rem; }

/* Image band on the first three cards — the reference leads each card
   with a picture. Cards 4+ keep a plain top so the grid still reads
   evenly when a product has more than three capabilities. */
[data-product] .pfeat__item:nth-child(-n+3)::before {
  content: "";
  display: block;
  aspect-ratio: 16 / 10;
  margin-bottom: 1.15rem;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  border-bottom: 1px solid rgba(255,255,255,.08);
}

/* The check becomes a small corner badge over the image. */
[data-product] .pfeat__check {
  position: absolute;
  top: .8rem;
  left: .8rem;
  z-index: 2;
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0,0,0,.5);
}
[data-product] .pfeat__item:nth-child(n+4) .pfeat__check {
  position: static;
  margin: 1.25rem 0 .75rem 1.25rem;
  display: inline-flex;
}

/* Per-product imagery for the three lead cards. */
[data-product="aquapilot-ai"]   .pfeat__item:nth-child(1)::before { background-image: url("/product/card-aquapilot.jpg"); }
[data-product="aquapilot-ai"]   .pfeat__item:nth-child(2)::before { background-image: url("/product/card-aquapilot-2.jpg"); }
[data-product="aquapilot-ai"]   .pfeat__item:nth-child(3)::before { background-image: url("/product/card-aquapilot-3.jpg"); }
[data-product="smart-sentry"]   .pfeat__item:nth-child(1)::before { background-image: url("/product/card-smart-sentry.jpg"); }
[data-product="smart-sentry"]   .pfeat__item:nth-child(2)::before { background-image: url("/product/card-smart-sentry-2.jpg"); }
[data-product="smart-sentry"]   .pfeat__item:nth-child(3)::before { background-image: url("/product/card-smart-sentry-3.jpg"); }
[data-product="ai-time-tracker"] .pfeat__item:nth-child(1)::before { background-image: url("/product/card-ai-tracker.jpg"); }
[data-product="ai-time-tracker"] .pfeat__item:nth-child(2)::before { background-image: url("/product/card-ai-tracker-2.jpg"); }
[data-product="ai-time-tracker"] .pfeat__item:nth-child(3)::before { background-image: url("/product/card-ai-tracker-3.jpg"); }
[data-product="postie-alert"]   .pfeat__item:nth-child(1)::before { background-image: url("/product/card-postie.jpg"); }
[data-product="postie-alert"]   .pfeat__item:nth-child(2)::before { background-image: url("/product/card-postie-2.jpg"); }
[data-product="postie-alert"]   .pfeat__item:nth-child(3)::before { background-image: url("/product/card-postie-3.jpg"); }

@media (max-width: 1099px) {
  [data-product] .pfeat__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  [data-product] .pfeat__list { grid-template-columns: minmax(0, 1fr); }
}

/* --- 24. product panels: intro + icon capability list ---------
   The stacked panels left ~1300x560px of dead space between the name and
   the description. It now carries the product's own intro line and its
   capability list, both taken verbatim from the matching product page on
   smart-tech.melbourne.

   Two pseudo-elements: ::before is the intro, ::after is the list. They
   are separate so the list can hold a per-line tick icon, drawn as a
   background tile whose height equals the line-height. Background images
   cannot inherit currentColor, so there are dark and light variants and
   each panel takes the one that reads on its own colour.

   left matches the panel's padding expression — absolute positioning
   resolves against the padding box, so left:0 would sit flush to the
   panel edge while the title sits at 48px. */
.products-panel__inner { position: relative; }

.products-panel__inner::before,
.products-panel__inner::after {
  position: absolute;
  left: clamp(1.25rem, 3.5vw, 3rem);
  right: 46%;
  color: inherit;
  font-family: var(--font-primary);
  white-space: pre-line;
  pointer-events: none;
}

.products-panel__inner::before {
  content: var(--panel-intro, "");
  top: 28%;
  max-width: 40ch;
  font-size: clamp(1rem, 1.3vw, 1.25rem);
  line-height: 1.55;
  opacity: .78;
}

.products-panel__inner::after {
  content: var(--panel-list, "");
  top: 46%;
  max-width: 34ch;
  padding-left: 1.85rem;
  font-size: clamp(.92rem, 1.1vw, 1.05rem);
  /* line-height and the icon tile height must match exactly, or the ticks
     drift away from their lines further down the list. */
  line-height: 2.1rem;
  background-repeat: repeat-y;
  background-size: 1.05rem 2.1rem;
  background-position: 0 0;
  opacity: .92;
}

@media (max-width: 900px) {
  .products-panel__inner::before,
  .products-panel__inner::after { display: none; }
}

.products-stack > :nth-child(1) .products-panel__inner {
  --panel-intro: "Real-time GPS tracking and AI-assisted route optimisation guide your boat safely through any waters.";
  --panel-list: "AI-Powered Navigation\A Weather & Tide Alerts\A AI-Assisted Docking\A 360° Obstacle Detection\A Automated SOS System";
  --panel-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111318' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 6.9'/%3E%3C/svg%3E");
}

.products-stack > :nth-child(2) .products-panel__inner {
  --panel-intro: "Custom AI models running on edge devices tell environmental movement from validated threats — with zero cloud dependency.";
  --panel-list: "360° Sensor Monitoring\A AI-Powered Threat Filtering\A Automated Strobe Activation\A Immediate Visual Deterrence\A Real-Time Incident Logging";
  --panel-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111318' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 6.9'/%3E%3C/svg%3E");
}

.products-stack > :nth-child(3) .products-panel__inner {
  --panel-intro: "Deployed silently to every employee device from your IT console, capturing sessions without manual clock-in.";
  --panel-list: "Silent Installation\A Session & Attendance\A Hardware Health\A USB & Peripheral Control\A Real-Time Alerts";
  --panel-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 6.9'/%3E%3C/svg%3E");
}

.products-stack > :nth-child(4) .products-panel__inner {
  --panel-intro: "An Australian IoT project combining smart mailbox technology, environmental monitoring and emergency response.";
  --panel-list: "Smart Mailbox Technology\A Sensor Fusion Technology\A Cloud Integration\A Wireless Communications\A Emergency Alert Systems";
  --panel-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111318' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 6.9'/%3E%3C/svg%3E");
}

.products-panel__inner::after { background-image: var(--panel-icon); }

/* --- 25. brand typography: serif headings ---------------------
   smart-tech.melbourne's own typography.css states the brand pairing:
   "Merriweather for headings, Poppins for body copy." The serif heading
   is the single biggest visual difference between the old site and this
   one, so display type moves to Merriweather.

   Body stays on Switzer rather than returning to Poppins — Poppins was
   tried and rejected earlier, and Switzer is the cleaner screen face at
   small sizes. */
:root {
  --font-display: "Merriweather", Georgia, "Times New Roman", serif;
}

/* Merriweather is a much heavier, wider face than the geometric sans it
   replaces: the old tracking and weights would look cramped and blunt. */
.hero__title, .svc__title, .approach__title, .whatwedo__text,
.whysmart__title, .products-panel__title, .products-panel__name,
.svc-hero__title, .phero__title, .fsplit__title, .pfeat__title,
.vgrid__title, .cform__title, .footer__intro-title {
  font-weight: 700 !important;
  letter-spacing: -.012em !important;
}
.hero__title, .svc__title { line-height: 1.12 !important; }
.whatwedo__text { line-height: 1.4 !important; }

/* The eyebrow labels stay sans — they are UI, not display type. */
.svc__eyebrow, .approach__eyebrow, .whatwedo__label, .pfeat__eyebrow,
.svc-hero__eyebrow, .footer__col-label, .cform__eyebrow {
  font-family: var(--font-primary) !important;
}

/* --- 12. service page split imagery --------------------------
   Three images per service page: the hero <img> (set in the route chunk)
   and the two .fsplit__visual blocks below it. All three must differ —
   when the Unsplash hotlinks were localised, each chunk hero was given
   the same file the first split block already used, so every service
   page repeated an image.

   The hero keeps the real illustration from smart-tech.melbourne; the
   two split blocks take brand renders. .fsplit--reverse is the second
   block and carries the extra class, so it outranks the first rule. */
[data-service] .fsplit__visual {
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-color: transparent;
  border-radius: 16px;
  min-height: 340px;
}
[data-service] .fsplit__visual .fsplit__card { display: none !important; }

[data-service="cloud"] .fsplit__visual { background-image: url("/service/alt-cloud.jpg") !important; }
[data-service="cloud"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="cybersecurity"] .fsplit__visual { background-image: url("/service/alt-security.jpg") !important; }
[data-service="cybersecurity"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="managed-it"] .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="managed-it"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-cloud.jpg") !important; }
[data-service="iot"] .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="iot"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="salesforce-crm"] .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="salesforce-crm"] .fsplit--reverse .fsplit__visual { background-image: url("/service/capabilities-iso-2.jpg") !important; }
[data-service="it-consulting"] .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="it-consulting"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="custom-app-development"] .fsplit__visual { background-image: url("/service/alt-security.jpg") !important; }
[data-service="custom-app-development"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="mobile-app-development"] .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="mobile-app-development"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-cloud.jpg") !important; }
[data-service="software-digital-design"] .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="software-digital-design"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }
[data-service="web-app-development"] .fsplit__visual { background-image: url("/service/alt-cloud.jpg") !important; }
[data-service="web-app-development"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-security.jpg") !important; }
[data-service="website-design"] .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="website-design"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-cloud.jpg") !important; }
[data-service="digital-marketing"] .fsplit__visual { background-image: url("/service/capabilities-iso-2.jpg") !important; }
[data-service="digital-marketing"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-security.jpg") !important; }
[data-service="domain-hosting"] .fsplit__visual { background-image: url("/service/alt-network.jpg") !important; }
[data-service="domain-hosting"] .fsplit--reverse .fsplit__visual { background-image: url("/service/alt-workflow.jpg") !important; }

/* --- 26. product pfeat: unstick the copy ----------------------
   .pfeat__copy is position:sticky — it was designed to hold in a side
   column while the capability list scrolled beside it. Section 23 stacks
   the copy above a 3-up grid instead, so sticky made the heading hover
   over the cards as they scrolled past. Static in the stacked layout;
   service pages keep their original two-column sticky behaviour. */
[data-product] .pfeat__copy { position: static !important; }

/* --- 27. product hero: drop the blank device mockup -----------
   Device.png is a generic iPhone render with an empty grey screen, used
   identically on all four product pages while its alt text claims to be
   the product ("AquaPilot AI marine navigation product"). It shows no
   product, so it is decoration pretending to be content — and it is the
   loudest thing in the hero. Removed. */
[data-product] .phero__mockup { display: none !important; }
/* .phero__center carries an explicit height:820px sized for the mockup, so
   hiding the child alone left an 820px hole in the hero. */
/* Collapsing it to 0 pulled .phero__banner-wrap up over the headline, so
   keep enough height for the banner to clear the copy — just not the 820px
   the mockup needed. */
[data-product] .phero__center { height: 0 !important; min-height: 0 !important; }
/* .phero__banner-wrap uses margin-top:-320px to tuck under the floating
   phone. With the phone gone that pulls it over the headline instead, so
   the negative margin has to go with it. */
[data-product] .phero__banner-wrap { margin-top: clamp(1.5rem, 3vw, 3rem) !important; }

/* --- 28. product panels: larger artwork -----------------------
   The panel image sat at 280px in a 1910px panel. Taking it to roughly
   half the panel width makes it the anchor it should be. The copy block
   is pulled back to match so the two never meet. */
.products-panel__visual {
  width: min(46vw, 880px) !important;
  height: auto !important;
  aspect-ratio: 4 / 3;
}
.products-panel__middle {
  width: auto !important;
  flex: 0 0 auto;
}
.products-panel__inner::before,
.products-panel__inner::after { right: 52%; }

/* --- 29. product hero: drop the placeholder partner banner ----
   The blue band carried invented partner names — AUSNET, GOVSAFE,
   COMMSHIELD, PARCELIO and IPSUM (the last is literally lorem ipsum).
   Presenting fabricated partners as real is worse than showing none,
   and the blue is off-brand against the red. Removed.
   With it gone the hero no longer needs the negative-margin dance. */
[data-product] .phero__banner-wrap { display: none !important; }

/* The hero CTA was the same off-brand blue. */
[data-product] .phero__cta {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
}
[data-product] .phero__cta:hover { background: var(--accent-hover) !important; }

/* --- 30. product panel artwork, larger still ------------------ */
.products-panel__visual {
  width: min(52vw, 1040px) !important;
  aspect-ratio: 4 / 3;
}
.products-panel__inner::before,
.products-panel__inner::after { right: 56%; }

/* --- 31. product panel: no number, image clear of the title ---
   The (01)/(02) counters are removed at the client's request, which also
   frees the width the artwork needed.

   At 4/3 the enlarged image grew tall enough to run into the panel title
   (measured: 199px horizontal, 55px vertical overlap). A 16/10 ratio
   keeps it just as wide but shorter, so it clears the heading. */
.products-panel__num { display: none !important; }

.products-panel__visual {
  width: min(52vw, 1040px) !important;
  aspect-ratio: 16 / 10;
  align-self: flex-end;
}
.products-panel__middle { align-items: flex-end; }
