/* Brand tokens and the WordPress preset colour classes live in brand.css,
   which is loaded ahead of this file. */

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  /* proxima-nova is the real theme's Adobe Fonts (Typekit) face -- it loads fine
     cross-domain, so we ask for it directly with a close system fallback chain */
  font-family: proxima-nova, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-weight: 400;
  letter-spacing: 0.5px;
  color: var(--body-text);
  line-height: 1.5;
  background: var(--text-white);
}
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
.site-main { overflow-x: hidden; }

/* GenerateBlocks renders every container as .gb-container > .gb-inside-container.
   The fetched per-page CSS puts flex/alignment on the OUTER .gb-container, but the
   actual content lives one level deeper -- GB's own base framework CSS makes the
   inner wrapper transparently inherit the outer's flex context, which our fetched
   CSS (block-instance styles only) doesn't include. Without this, only the wrapper
   itself gets centered/aligned and its children fall back to default block flow. */
.gb-container {
  /* GenerateBlocks' own default for an unstyled flex container is flex-start,
     not the raw CSS initial "stretch" -- this is what keeps a button (or any
     other auto-sized child) from stretching full-width when its container
     doesn't request a specific alignment. A container that explicitly sets
     align-items (e.g. the homepage hero's align-items:center) overrides this
     via its own higher-specificity per-instance rule, so real centering still
     wins. Only affects elements once display:flex is actually on; harmless
     no-op otherwise. */
  align-items: flex-start;
}
.gb-container > .gb-inside-container {
  display: inherit;
  flex-direction: inherit;
  flex-wrap: inherit;
  align-items: inherit;
  justify-content: inherit;
  row-gap: inherit;
  column-gap: inherit;
  width: 100%;
  min-width: 0;
}

/* GenerateBlocks grids rely on flex-wrap + percentage-width columns rather than
   an explicit width on the wrapper itself. That's fine normally, but it creates a
   circular layout dependency when a column contains a JS-measured carousel: the
   wrapper's width depends on its children's content, the carousel's width depends
   on measuring its column, which depends on the wrapper. Slick catches an unstable
   intermediate measurement and locks it in via inline pixel widths. A firm
   top-down width on the wrapper (and letting columns actually shrink) breaks
   the cycle. */
/* min-width, not width. GenerateBlocks grids widen themselves past their
   container with a negative side margin (this page's wrapper carries
   margin-left:-80px, matched by 80px of padding on each column). A fixed
   width:100% pins the box to the container so the negative margin only shifts
   it left instead of widening it -- costing 80px and wrapping the customer area
   document titles onto two lines. min-width keeps the determinate width Slick
   needs to measure against while letting those grids expand. */
.gb-grid-wrapper { min-width: 100%; }
.gb-grid-column { min-width: 0; }

/* ---------- headline defaults ---------- */
/* h1/h2 size and weight are pinned by the theme's own CSS (!important); these
   are fallbacks for headline levels the theme doesn't touch */
h1.gb-headline, h2.gb-headline, h3.gb-headline, h4.gb-headline { margin: 0; line-height: 1.2; font-weight: 700; }
h3.gb-headline { font-size: 1.3rem; }
/* 1rem bottom margin, matching live -- theme.css gives every <p> 1rem and the
   per-instance generated CSS overrides it where a headline needs something
   else. Forcing 0 here flattened that: it removed the gap between a testimonial
   quote and its attribution, and between headline paragraphs generally.
   Measured against live, 28 of 35 headline paragraphs on the homepage land on
   exactly live's 16px with this. */
p.gb-headline { margin: 0 0 1rem; }
.gb-headline mark { background: transparent; padding: 0; }
/* Every heading's trailing "." is a decorative <mark> carrying whatever
   WP preset colour it happened to be authored with (pink, secondary,
   the old "highlight-marketing" magenta...) -- a leftover from when
   that dot doubled as a colour-switcher preview. Now that each service
   page has one consistent accent colour, that mix of unrelated dot
   colours reads as off-brand noise. Recolouring them all to the page's
   own accent is the most consistent option: it matches every other
   accent-coloured element already on the page instead of introducing a
   new colour meaning just for the dot.
   Two things keep this from over-reaching: (1) :is(h1,h2,h3,h4) rather
   than matching by class -- headings on this site are authored as
   either .gb-headline (GenerateBlocks) or .wp-block-heading (plain WP
   core heading block) more or less interchangeably, and .gb-headline
   is ALSO used on <p class="gb-headline"> paragraphs (whose marks
   highlight whole sentences and aren't part of this dot pattern at
   all), so matching by element type only -- not requiring either
   class -- is what actually catches every heading correctly rather
   than silently missing whichever one wasn't the class checked for
   ("Explore More Devices." on the product pages used wp-block-heading
   and was invisible to a .gb-headline-only version of this rule).
   (2) :last-child, since some headings carry extra marks for
   individually-coloured words earlier in the title (e.g. "Microsoft
   365 Licence Management.") -- only the final mark is ever the dot.
   Scoped via body[style*="--service-accent"] rather than var()'s own
   fallback, since a fallback here would force one colour onto every
   dot on the rest of the site too; this attribute selector only
   matches pages whose <body> actually carries that inline custom
   property, so it's a genuine no-op everywhere else. */
body[style*="--service-accent"] :is(h1, h2, h3, h4) mark:last-child {
  color: var(--service-accent) !important;
}
/* Exception: on these 28 headings the text right next to the dot is
   white (product-carousel slide titles, and full-width sections
   authored with white text against a coloured/dark background), so an
   accent-coloured dot would either vanish into an identically-coloured
   background or clash with white neighbouring text. The dot follows
   its neighbour's colour instead, same rule as the accent one above:
   uniform white here (not a random mix) reads as consistent, so it
   still solves the original "off-brand noise" complaint. Identified by
   checking the actual rendered colour of the text/mark immediately
   before each dot across all 5 pages, not by guesswork.
   Grouped under :is() and re-adding the body attribute + .gb-headline
   class (already implied, but repeated here) so this beats the general
   rule above on specificity -- a bare per-instance class selector alone
   would tie on element count and lose to the general rule's extra
   :is(h1,h2,h3,h4) element. */
body[style*="--service-accent"] .gb-headline:is(
  .gb-headline-a5cab2d7, .gb-headline-9d7b8720, .gb-headline-e8f25ba9,
  .gb-headline-3a3d5834, .gb-headline-6c25b553, .gb-headline-41af14ae,
  .gb-headline-b07de1a5, .gb-headline-e46c08c8, .gb-headline-dcf6bb95,
  .gb-headline-60818d6a, .gb-headline-2efb6a31, .gb-headline-b909864c,
  .gb-headline-0a9051f1, .gb-headline-696e5d7a, .gb-headline-b75cf0ec,
  .gb-headline-2099f82f, .gb-headline-2156f1ee, .gb-headline-1fddfbc8,
  .gb-headline-8b92a5e6, .gb-headline-ba552ee1, .gb-headline-85c50525,
  .gb-headline-dc92313e, .gb-headline-07a7ebd0, .gb-headline-6b9aeea6,
  .gb-headline-20bcd56b, .gb-headline-744a6250, .gb-headline-5a1beac1,
  .gb-headline-17943dec
) mark:last-child {
  color: #fff !important;
}
/* Same exception, same reasoning, for the product pages (Yealink
   phones, routers, RMM, etc.) now themed via SERVICE_ACCENTS too: their
   "Get in Touch." heading and a shared "Central ... Dashboard." /
   "Clear Customer Visibility." / etc. hero-block heading (a single
   GenerateBlocks reusable instance reused verbatim across many of these
   pages, hence one class covering several different heading texts) both
   have white heading text, so their dots need to stay white for the
   same reason as above. Just 7 unique instance classes cover all ~44
   affected headings across ~32 pages, since GenerateBlocks reuses the
   same instance id wherever the template block is identical. */
body[style*="--service-accent"] .gb-headline:is(
  .gb-headline-2d555531, .gb-headline-5497e424, .gb-headline-817f7bb5,
  .gb-headline-aee25fea, .gb-headline-e4fd3ab7-8171-4127-9fbc-e48c5e8ad822,
  .gb-headline-ed387cc9, .gb-headline-f39e7668
) mark:last-child {
  color: #fff !important;
}
/* "Explore More Devices." is a wp-block-heading (not .gb-headline), so it
   was never caught by the class-scoped exceptions above -- it sits on the
   same accent-coloured band as its white heading text, so the dot needs
   to stay white too. Shared id across every product page, so one rule
   covers all of them. */
body[style*="--service-accent"] #h-explore-more-devices mark:last-child {
  color: #fff !important;
}

/* ---------- buttons ---------- */
/* Base, safe for every button including icon-only ones. */
.gb-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: background-color .2s ease, color .2s ease;
}
/* Pill styling only for buttons that carry a label. GenerateBlocks adds
   .gb-button-text when a button has text, so this leaves icon-only buttons
   alone -- the customer area's view/download links are bare <a> icons whose
   per-instance CSS deliberately sets no padding or background, and blanket
   .gb-button padding inflated each one from 24x16 to 61x33.
   Every button on the site has per-instance CSS (449 of 449), so this is a
   brand default for anything newly authored rather than a repair.

   Matched via :where() so the extra class contributes no specificity. As a
   plain .gb-button.gb-button-text it scores (0,2,0) and beats the per-instance
   a.gb-button-{id} rules at (0,1,1), overriding their real padding. */
.gb-button:where(.gb-button-text) {
  font-weight: 400;
  padding: 0 28px;
  border-radius: 999px;
  background-color: var(--brand-btn-bg);
  color: var(--brand-btn-text);
}
.gb-button:where(.gb-button-text):hover { background-color: var(--secondary); color: var(--text-white); }

/* Every CTA button ships its own per-instance height/radius from WordPress
   (449 separate generated CSS files -- one per post -- each hand-authored
   with a slightly different padding/radius over the years), so the same
   "Get in touch" label ends up 34px tall and square on one page, 52px and
   fully round on another. Force every one to the height+shape of the
   reference button ("Get in touch" under The Basics on Cloud Phone
   Systems: 40px tall, fully rounded) so the site reads as one consistent
   button style. Colour and hover are untouched -- only geometry changes.
   Horizontal padding is left alone here, so width still tracks each
   button's own label length rather than being forced identical -- widths
   are standardised separately below, per label, once heights/radii are
   already uniform.
   Accordion toggles (full-width expand/collapse rows, not pill CTAs) and
   the fixed header's "Get in touch" link (a bare <a>, no .gb-button class
   at all) are naturally out of scope -- neither carries .gb-button-text.
   The one CTA without that class is the native <button type="submit">
   contact-form Submit, added explicitly below.

   One height for every button (Simon, 2026-09-23: "some are taller than
   others -- make sure all button heights are the same across the
   website"). An audit found pills at 36, 40, 44, 47 and 53px depending
   on which rule owned them. 48px (the house phone pill) was tried first,
   then 40, and settled at 44px once served. THIS rule is where the
   height lives: the house pills (.fone-cta-btn, .fone-hw-btn), the
   contact form's Send and the fixed header's "Get in touch" join the
   .gb-button CTAs here, so nothing sizes a button on its own any more.
   The label is centred by flex, not by padding arithmetic ("should be
   dead centre", Simon): at 40px the 6px/6px padding left a 28px content
   box round a 24px line, and every block-laid-out pill (.fone-cta-btn,
   .fone-hw-btn) drew its text 2px high. align-items centres a label of
   any line-height at any height, so a later change to this one number
   can't put the text off again. The header link keeps theme.css's 5px
   corners (only the pills take the radius, second rule); its colour,
   hover and weight are untouched. Also written up in
   _build/README-branding.md ("One height for every button"). */
:is(
  a.gb-button.gb-button-text,
  button.gb-button.gb-button-text,
  button.gb-button[type="submit"],
  .wp-contact-form button[type="submit"],
  .fone-cta-btn,
  .fone-hw-btn,
  .site-header .gb-button-wrapper a
):not(.gb-accordion__toggle) {
  height: 44px !important;
  min-height: 44px !important;
  box-sizing: border-box !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
:is(
  a.gb-button.gb-button-text,
  button.gb-button.gb-button-text,
  button.gb-button[type="submit"],
  .wp-contact-form button[type="submit"],
  .fone-cta-btn,
  .fone-hw-btn
):not(.gb-accordion__toggle) {
  border-radius: 999px !important;
}

/* Same button, same label, same width -- site-wide. Auditing every CTA by
   its actual rendered text (not by class: GenerateBlocks reuses instance
   classes across pages, and the same class sometimes carries different
   text on different pages, e.g. .gb-button-a5ae33cb is "Get in touch" on
   Cloud Phone Systems but "Find out more" on Care Homes -- a class list
   alone can't safely stand in for "this text") turned up three labels
   whose width varies purely because of per-instance padding/font-weight
   left over from the WordPress export, not because the text differs:
   "Get in touch" (111 instances, 118-138px), the phone number (56
   instances, 133-139px) and "Find out more" (101 instances, 128-152px).

   The width chosen for each label is its measured text width (canvas-
   measured at 16px/700-weight/0.5px letter-spacing, the widest of the
   two font-weights in use, via document.fonts.ready so it's the real
   proxima-nova metric, not a fallback font's) plus this rule's own
   12px/side padding plus the 2px/side transparent border several of
   these instances reserve for hover (see the Blue>White/White>fill
   block above) -- e.g. "Get in touch" measures 94.4px, +24 padding +4
   border = 122.4px required. The first version of this rule used
   exactly that required figure with no slack, on the assumption it
   matched the live reference button under The Basics pixel-for-pixel.
   It doesn't leave any margin for real-world rendering variance
   (subpixel rounding, font hinting, OS/display scaling), and in
   practice the text wraps to two lines and blows out the pill -- this
   is the site-wide "buttons rendering broken" bug. Each width below
   adds roughly 8px of slack beyond the bare-minimum figure so a few
   pixels of rendering variance can never tip it into wrapping again.
   "Get in touch" and the phone number both always link to one fixed
   destination (/contact-us/, tel:03302211183), so an attribute selector
   picks them out precisely -- including the one "Get in Touch" instance
   with a capital T -- without touching the shared classes' other uses.
   "Find out more" has no fixed href (a different product on every page),
   so it's matched by its full, audited list of 60 instance classes
   instead; none of them are shared with a "Get in touch" or phone
   instance, so this list and the two attribute rules can't collide.
   Other labels ("Submit", "Login here"...) either already match within
   their own group or -- "Submit" -- are sized to fit their own form
   column rather than their text, so they're left alone. "Read our
   reviews" had the same zero-margin problem (132.8px text in a 133px
   budget) and is fixed the same way, just below. */
a.gb-button.gb-button-text[href="/contact-us/"] {
  width: 130px !important;
  padding-left: 12px !important;
  padding-right: 12px !important;
}
a.gb-button.gb-button-text[href="tel:03302211183"] {
  width: 148px !important;
  padding-left: 12px !important;
  padding-right: 12px !important;
}
.gb-button.gb-button-text:is(
  .gb-button-03592781, .gb-button-0374bb26, .gb-button-0f414125,
  .gb-button-10a19c4c, .gb-button-127618f9, .gb-button-17604e06,
  .gb-button-1cbae936, .gb-button-23da967d, .gb-button-2a554eae,
  .gb-button-340a85e4, .gb-button-35837cdd, .gb-button-3971330f,
  .gb-button-43a0a727, .gb-button-45bc2c11, .gb-button-4ecda2d3,
  .gb-button-4f7ed94a, .gb-button-522c9106, .gb-button-52467db6,
  .gb-button-53bf5792, .gb-button-57bb86cc, .gb-button-5b612436,
  .gb-button-5ef32f24, .gb-button-644b9a60, .gb-button-64db1e83,
  .gb-button-65de39ee, .gb-button-661fe1c6, .gb-button-6883640f,
  .gb-button-6b245ba9, .gb-button-6e69d1f7, .gb-button-7776f200,
  .gb-button-78e279ee, .gb-button-7c8bdf41, .gb-button-7ec1a8d0,
  .gb-button-83e29af2, .gb-button-845cca54, .gb-button-860f6174,
  .gb-button-8e1c1437, .gb-button-9526648b, .gb-button-99a8239f,
  .gb-button-99d6ea14, .gb-button-a4127de0, .gb-button-a5ae33cb,
  .gb-button-a694b716, .gb-button-a7814829, .gb-button-ab9f20c7,
  .gb-button-afd606c8, .gb-button-b7e6f602, .gb-button-bce431c6,
  .gb-button-bfbcaa45, .gb-button-c431ed7d, .gb-button-c70867a6,
  .gb-button-ccece3b5, .gb-button-d237b173, .gb-button-d6cbc4b1,
  .gb-button-e51f3077, .gb-button-e59a154a, .gb-button-e80c935e,
  .gb-button-f191adbb, .gb-button-ff2ed986, .gb-button-ff6e1240
) {
  width: 144px !important;
  padding-left: 12px !important;
  padding-right: 12px !important;
}
/* .gb-button-a5ae33cb is reused for a *third* label too -- "Read our
   reviews" on Wifi & Networking -- so the find-out-more list above just
   caught it and shrank it, off from its already-consistent sibling
   (Internet Connectivity, same href, same width). Restore it via that
   shared Google-reviews href, which beats the class list on specificity
   the same way the get-in-touch/phone rules do. Widened from the
   original 177px for the same reason as the other three labels above:
   132.8px of text plus 40px padding plus 4px border left only 0.2px of
   slack, which is why it broke too.
   A *fourth* label -- "Read our Google reviews" under Client Feedback
   on F One Technologies -- links to this exact same review URL, so this
   rule was also silently catching it and wrapping its longer text (it
   needs 235px, not 185px) to two lines. Rather than excluding it by its
   one current instance's class (which would only protect this specific
   button and miss the same text if it's ever added to another page),
   :not(:has(> strong)) excludes it structurally: uniquely among these
   four labels, this one's markup wraps its text in <strong>, so the
   distinction holds site-wide regardless of which instance class
   GenerateBlocks happens to assign it on any given page. */
a.gb-button.gb-button-text[href*="google.com/search"]:not(:has(> strong)) {
  width: 185px !important;
  padding-left: 20px !important;
  padding-right: 20px !important;
}
/* "Read our Google reviews": same href as "Read our reviews" above, but
   its text is <strong>-wrapped, which is what the rule above excludes
   on -- see that comment. 192.5px text + 30px padding + 4px border =
   226.5px minimum, +8px slack. Site-wide by construction: matches this
   label wherever it appears, not tied to today's one known instance. */
a.gb-button.gb-button-text[href*="google.com/search"]:has(> strong) {
  width: 235px !important;
  padding-left: 15px !important;
  padding-right: 15px !important;
}

/* Breathing room above in-page buttons.
   Every button ships with margin-top:0 and the per-instance GenerateBlocks CSS
   only sets padding, so content buttons sat flush against the paragraph above
   them. This is external space on purpose -- padding-top would grow the button
   box and push the label off centre, and would have to fight the eight
   different per-instance padding values in use across the site.

   Scoped to .site-main so the fixed header bar's "Get in touch" CTA (and the
   footer) are untouched. Hero buttons already get 20px from their container's
   row-gap, so they land at 40px, which reads as intentional.

   Restricted to buttons carrying a label (.gb-button-text): icon-only buttons
   such as the customer area's view/download links are inline row controls, and
   20px of lead-in pushed each row 17px taller than live.

   Only 4px is added here now: the p.gb-headline fix restored live's 16px
   paragraph margin below the preceding copy, so the two stack. 20px on top of
   that came to 36px, noticeably looser than the 20px total signed off earlier.

   NB: this is a deliberate divergence from the live WordPress site, which has
   no such rule -- see the note in _build/README-branding.md. */
.site-main a.gb-button.gb-button-text,
.site-main .gb-button-wrapper a,
.site-main .wp-block-button a {
  margin-top: 4px;
}

/* accordion toggle buttons look like plain rows, not pill buttons */
.gb-accordion__toggle {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  background: var(--text-white);
  color: var(--purple);
  padding: 0;
  border-radius: 0;
  text-align: left;
  font-weight: normal;
}
.gb-accordion__toggle:hover { background: var(--text-white); color: var(--secondary); }
.gb-icon { display: inline-flex; width: 0.8em; height: 0.8em; margin-left: 10px; flex-shrink: 0; }
.gb-accordion__icon-open { display: none; }
/* Direct paths only (item > toggle on the hand-authored pages, item >
   .gb-inside-container > toggle in gbrender.py's output): the descendant
   form let an open parent accordion flip the chevron and colour of every
   toggle nested inside it -- the Customer Area's 2024/2025/2026 rows
   showed the "open" chevron while still closed (2026-09-23). */
.gb-accordion-item.is-open > .gb-accordion__toggle .gb-accordion__icon,
.gb-accordion-item.is-open > .gb-inside-container > .gb-accordion__toggle .gb-accordion__icon { display: none; }
.gb-accordion-item.is-open > .gb-accordion__toggle .gb-accordion__icon-open,
.gb-accordion-item.is-open > .gb-inside-container > .gb-accordion__toggle .gb-accordion__icon-open { display: inline-flex; }
.gb-accordion-item.is-open > .gb-accordion__toggle,
.gb-accordion-item.is-open > .gb-inside-container > .gb-accordion__toggle { color: var(--secondary); }

/* ---------- accordion slide ---------- */
.gb-accordion-content {
  overflow: hidden;
  transition: max-height .25s ease, padding .25s ease;
}
/* the block's own inline padding (from its WP attrs) beats a plain class rule,
   so force it to zero while collapsed rather than fighting specificity.
   margin-bottom is each instance's own per-page WordPress export value
   (20px on Cloud Phone Systems) and, unlike padding, isn't cleared just
   by max-height:0 -- with the content div's own height already at 0 while
   collapsed, that margin *is* the entire visible gap between one row's
   toggle and the next row's toggle. Pulled down to 4px for a visibly
   tighter stack of rows; not 0, so closed rows still read as separate
   lines rather than one fused block. */
.gb-accordion-item:not(.is-open) .gb-accordion-content {
  max-height: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  margin-bottom: 4px !important;
}

/* ---------- video embeds ---------- */
.video-embed { position: relative; width: 100%; padding-top: 56.25%; }
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ---------- dynamic content notice (things that were live/dynamic on WP) ---------- */
.dynamic-notice {
  padding: 1em;
  border: 1px dashed rgba(0,0,0,.2);
  border-radius: 8px;
  font-size: .9rem;
  font-style: italic;
  opacity: .75;
}

/* ---------- contact form placeholder ---------- */
/* One width for every contact form: 480px, the contact page's Message the
   Team form (Simon, 2026-09-24: "all the contact forms across the entire
   site uniform in width, using the contact us page as the guide"). They
   were coming out at three widths: 480 there, 462 in the house
   .fone-contact-card (its 526px media column less the card's padding),
   and 338 in the WordPress "Get in Touch" cards, whose flex-start column
   let the form shrink to its widest field's own width. A fixed 480px,
   capped at the container on phones, settles all of them: the
   shrink-wrapped cards grow to 544px round it, and the house card's media
   column is pinned to that same 544px (below) so its form is 480 too. The
   contact page's Request a Quote tool keeps its own width ("keep the
   current width"). */
.wp-contact-form { display: flex; flex-direction: column; gap: 12px; width: 480px; max-width: 100%; }
.request-quote-form .wp-contact-form { width: auto; }
/* Five of the WordPress "Get in touch" panels (the service landing pages
   and About Us) were exported with 2.5em padding where every other one
   has 2em; round a 480px form that made them 560px in a 550px column.
   All of them get the 2em the rest have, so every panel is 544px. The
   per-instance rule loads after this file, hence !important. */
:is(.gb-container-b1471337, .gb-container-1d647e8a) > .gb-inside-container:has(> .wp-contact-form-wrap) { padding: 2em !important; }
.wp-contact-form label { font-size: .9rem; font-weight: 600; }
.wp-contact-form input, .wp-contact-form textarea {
  width: 100%;
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid rgba(0,0,0,.15);
  font-family: inherit;
  font-size: .95rem;
}
.wp-contact-form textarea { min-height: 100px; resize: vertical; }
/* Both contact forms sit inside dark sections whose text colour is orange, and
   labels would otherwise inherit it -- unreadable on the deep blue. Live sidesteps
   this by using placeholders with no visible labels; keeping real labels is better
   for accessibility, so they get an explicit colour instead. */
.wp-contact-form-wrap { color: var(--text-white); }
.wp-contact-form label { color: var(--text-white); }
.wp-contact-form select {
  width: 100%;
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid rgba(0,0,0,.15);
  font-family: inherit;
  font-size: .95rem;
  background: var(--text-white);
  color: var(--text-black);
}
.wp-contact-form input[type="range"] { padding: 0; accent-color: var(--primary); }
.wp-contact-form output { font-weight: 700; color: var(--text-white); }
.form-note { font-size: .78rem; opacity: .8; margin-top: 8px; color: var(--text-white); }
/* The form's Send button is the house pill on a coloured band (Simon,
   2026-09-23: "contact forms have buttons that don't match the page's
   colour theme"). theme.css's generic `button { background: #f06120;
   border: 1px solid; border-radius: 3px; padding: .6em 1em .4em }` left
   it a square-cornered box in the system font, and its hover went navy
   (var(--secondary)) whatever the page colour -- on Elevate's blue card
   or IT Essentials' purple one that navy belonged to neither, and on the
   navy cards of /contact-us/ and the industry pages the button simply
   vanished into its own background. Now the same shape as every other
   CTA (the 40px pill the .gb-button rule above standardises) and the
   same hover system as `.bg-brand .fone-cta-btn` further down: white
   with the page colour as text at rest, filling with the page colour
   under a white 2px inset line and 1px ring on hover. The inset line is
   a shadow, not a border, so the button never changes size.
   var(--service-accent, #f06120) means a page with no accent (contact-us
   itself, the industry pages) keeps the site orange, as its heading dot
   does. Scoping to .wp-contact-form outranks theme.css's element rule
   and its :hover/:focus/:active variants alike. */
.wp-contact-form button[type="submit"] {
  height: 44px;
  padding: 0 28px;
  border: 0;
  border-radius: 999px;
  background: #fff;
  color: var(--service-accent, #f06120);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.wp-contact-form button[type="submit"]:hover,
.wp-contact-form button[type="submit"]:focus,
.wp-contact-form button[type="submit"]:active {
  background: var(--service-accent, #f06120);
  color: #fff;
  box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #fff;
}
/* On a page with no accent the card is navy, not the page colour, so the
   white-at-rest pattern above is the wrong way round there (Simon,
   2026-09-23, /contact-us/: "should be orange and the hover to clear").
   Filled orange at rest, clearing to white with orange text, a 2px
   inset orange line and a 1px ring -- the same Filled > White hover as
   every other orange pill on these pages (see the "pages with no
   service accent" block further down). Themed pages keep the rule
   above: their card IS the page colour, so the white pill is right. */
body:not([style*="--service-accent"]) .wp-contact-form button[type="submit"] {
  background: var(--primary, #f06120);
  color: #fff;
}
body:not([style*="--service-accent"]) .wp-contact-form button[type="submit"]:is(:hover, :focus, :active) {
  background: #fff;
  color: var(--primary, #f06120);
  box-shadow: inset 0 0 0 2px var(--primary, #f06120), 0 0 0 1px var(--primary, #f06120);
}
/* The "Customisable On-Hold Marketing Messages" (SmartVoice) section on
   the Cloud Phone Systems page is hardcoded pink in its own per-page
   generated stylesheet (static/css/generated/215.css), which loads
   after this file -- needs !important to still win. Page-specific
   selector, so this can't leak onto any other page. */
.gb-container-60ee8c42 { background-color: var(--service-accent, #CC289C) !important; }
/* Same section also has a decorative wave shape (SVG fill via currentColor)
   hardcoded pink in 215.css -- that's the pink still visible behind/around
   the blue container. Scoped to this exact shape only. */
.gb-container-60ee8c42 > .gb-shapes .gb-shape-2 { color: var(--service-accent, #CC289C) !important; }
/* Its "Find out more" button also has hardcoded pink text
   (a.gb-button-1cbae936 in 215.css). Scoped to this one button. */
a.gb-button-1cbae936 { color: var(--service-accent, #CC289C) !important; }

/* The dedicated SmartVoice product page (/smartvoice-on-hold-messaging/,
   blue-themed) has the same hardcoded-pink pattern on two of its own
   buttons: gb-button-1d2e8637 has a pink rest background, and
   gb-button-e9849ba3 has pink rest text. Both classes are reused
   verbatim on several other (correctly-coloured) pages too -- not
   scoped to this one page, since var(--service-accent) already
   resolves correctly per page and harmlessly reconfirms the existing
   right answer everywhere else. */
a.gb-button-1d2e8637 { background-color: var(--service-accent, #76C0FF) !important; }
a.gb-button-e9849ba3 { color: var(--service-accent, #CC289C) !important; }

/* Every filled CTA button gets the same hover inversion + 8102
   outline/glow ring (copied from the command console's
   .mega-tab.is-active), split into two groups by their rest fill:
   blue-filled buttons ("The Basics" etc.) invert to a white fill on
   hover; white-filled buttons ("Find out more" variants, the feature
   grid) stay filled but flip to the accent colour on hover, with a
   WHITE ring+glow (not accent-coloured) -- these sit on blue section
   backgrounds already, so an accent-coloured fill+ring would disappear
   into its own backdrop; white stays visible either way. A full 2px
   solid border is set on hover throughout, matching the feature-grid
   buttons' own native 2px border -- those also carry a hardcoded pink
   border-color on hover in their per-page generated CSS, which this
   overrides too. Most of the other buttons have no border at rest at
   all, so a border appearing only on hover grew their box by 4px and
   nudged surrounding text -- giving every button a transparent 2px
   border at rest (below) reserves the same space up front so hover
   only recolours it, never resizes it, exactly like the feature-grid
   buttons already do natively.

   Originally built for Cloud Phone Systems specifically, but every
   selector here is a bare class name with no page scoping -- and
   GenerateBlocks turned out to reuse several of these exact same
   instance ids across the ~35 individual product pages under each
   service (confirmed: gb-button-a5ae33cb and -13b5fd90 were already
   silently working correctly there before this class list even grew,
   since var(--service-accent) always resolves to whichever page is
   actually being viewed). Classes below with no comment of their own
   were added later specifically to close the same gap for the several
   product-page button ids that weren't already covered by chance.
   !important throughout since these tie
   on specificity with 215.css's own per-instance rules (incl. its own
   hover rules), which load after this file. */
a.gb-button-424478e8,
a.gb-button-a5ae33cb,
a.gb-button-009f904b,
a.gb-button-f25c87bf,
a.gb-button-99d6ea14,
a.gb-button-9dd83a88,
a.gb-button-13b5fd90,
a.gb-button-e59a154a,
a.gb-button-2a554eae,
a.gb-button-53bf5792,
a.gb-button-3971330f,
a.gb-button-7776f200,
a.gb-button-ab9f20c7,
a.gb-button-661fe1c6,
a.gb-button-c70867a6,
a.gb-button-644b9a60,
a.gb-button-78e279ee,
a.gb-button-860f6174,
a.gb-button-10a19c4c,
a.gb-button-8e1c1437,
a.gb-button-0374bb26,
a.gb-button-afd606c8,
a.gb-button-a694b716,
a.gb-button-845cca54,
a.gb-button-a7814829,
a.gb-button-7c8bdf41,
a.gb-button-544ee991,
a.gb-button-1cbae936,
a.gb-button-1d2e8637,
a.gb-button-32c7ad69,
a.gb-button-b020a5b7,
a.gb-button-e9849ba3 {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Blue > White */
a.gb-button-424478e8:hover, a.gb-button-424478e8:focus, a.gb-button-424478e8:active,
a.gb-button-a5ae33cb:hover, a.gb-button-a5ae33cb:focus, a.gb-button-a5ae33cb:active,
a.gb-button-009f904b:hover, a.gb-button-009f904b:focus, a.gb-button-009f904b:active,
a.gb-button-f25c87bf:hover, a.gb-button-f25c87bf:focus, a.gb-button-f25c87bf:active,
a.gb-button-99d6ea14:hover, a.gb-button-99d6ea14:focus, a.gb-button-99d6ea14:active,
a.gb-button-9dd83a88:hover, a.gb-button-9dd83a88:focus, a.gb-button-9dd83a88:active,
a.gb-button-13b5fd90:hover, a.gb-button-13b5fd90:focus, a.gb-button-13b5fd90:active,
a.gb-button-1d2e8637:hover, a.gb-button-1d2e8637:focus, a.gb-button-1d2e8637:active,
a.gb-button-32c7ad69:hover, a.gb-button-32c7ad69:focus, a.gb-button-32c7ad69:active {
  background-color: #fff !important;
  color: var(--service-accent, #76C0FF) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #76C0FF) !important;
}
/* White (stays filled) > accent fill + white ring */
a.gb-button-e59a154a:hover, a.gb-button-e59a154a:focus, a.gb-button-e59a154a:active,
a.gb-button-2a554eae:hover, a.gb-button-2a554eae:focus, a.gb-button-2a554eae:active,
a.gb-button-53bf5792:hover, a.gb-button-53bf5792:focus, a.gb-button-53bf5792:active,
a.gb-button-3971330f:hover, a.gb-button-3971330f:focus, a.gb-button-3971330f:active,
a.gb-button-7776f200:hover, a.gb-button-7776f200:focus, a.gb-button-7776f200:active,
a.gb-button-ab9f20c7:hover, a.gb-button-ab9f20c7:focus, a.gb-button-ab9f20c7:active,
a.gb-button-661fe1c6:hover, a.gb-button-661fe1c6:focus, a.gb-button-661fe1c6:active,
a.gb-button-c70867a6:hover, a.gb-button-c70867a6:focus, a.gb-button-c70867a6:active,
a.gb-button-644b9a60:hover, a.gb-button-644b9a60:focus, a.gb-button-644b9a60:active,
a.gb-button-78e279ee:hover, a.gb-button-78e279ee:focus, a.gb-button-78e279ee:active,
a.gb-button-860f6174:hover, a.gb-button-860f6174:focus, a.gb-button-860f6174:active,
a.gb-button-10a19c4c:hover, a.gb-button-10a19c4c:focus, a.gb-button-10a19c4c:active,
a.gb-button-8e1c1437:hover, a.gb-button-8e1c1437:focus, a.gb-button-8e1c1437:active,
a.gb-button-0374bb26:hover, a.gb-button-0374bb26:focus, a.gb-button-0374bb26:active,
a.gb-button-afd606c8:hover, a.gb-button-afd606c8:focus, a.gb-button-afd606c8:active,
a.gb-button-a694b716:hover, a.gb-button-a694b716:focus, a.gb-button-a694b716:active,
a.gb-button-845cca54:hover, a.gb-button-845cca54:focus, a.gb-button-845cca54:active,
a.gb-button-a7814829:hover, a.gb-button-a7814829:focus, a.gb-button-a7814829:active,
a.gb-button-7c8bdf41:hover, a.gb-button-7c8bdf41:focus, a.gb-button-7c8bdf41:active,
a.gb-button-544ee991:hover, a.gb-button-544ee991:focus, a.gb-button-544ee991:active,
a.gb-button-1cbae936:hover, a.gb-button-1cbae936:focus, a.gb-button-1cbae936:active,
a.gb-button-b020a5b7:hover, a.gb-button-b020a5b7:focus, a.gb-button-b020a5b7:active,
a.gb-button-e9849ba3:hover, a.gb-button-e9849ba3:focus, a.gb-button-e9849ba3:active {
  background-color: var(--service-accent, #76C0FF) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}
/* The one white-bg button that isn't blue-themed: the WhatsApp
   section's CTA keeps its own green branding rather than the page's
   blue accent, so it fills with its own green on hover, same white
   ring treatment as the group above. */
a.gb-button-57bb86cc {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
a.gb-button-57bb86cc:hover, a.gb-button-57bb86cc:focus, a.gb-button-57bb86cc:active {
  background-color: var(--wp--preset--color--wsa-green, #2ACC63) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* ============ internet-connectivity ============ */
/* Same Blue>White / White(fill)>accent+white-ring hover system as Cloud
   Phone Systems, ported to this page's own buttons and accent colour.
   Transparent 2px border reserved at rest so hover only recolours it
   (no layout nudge); !important throughout to beat this page's own
   per-instance generated CSS, which loads after this file. */
a.gb-button-424478e8,
a.gb-button-a52fc654,
a.gb-button-2114d9a1,
a.gb-button-99a8239f,
a.gb-button-13b5fd90,
a.gb-button-64db1e83 {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Blue > White */
a.gb-button-424478e8:hover, a.gb-button-424478e8:focus, a.gb-button-424478e8:active,
a.gb-button-a52fc654:hover, a.gb-button-a52fc654:focus, a.gb-button-a52fc654:active,
a.gb-button-2114d9a1:hover, a.gb-button-2114d9a1:focus, a.gb-button-2114d9a1:active,
a.gb-button-99a8239f:hover, a.gb-button-99a8239f:focus, a.gb-button-99a8239f:active,
a.gb-button-13b5fd90:hover, a.gb-button-13b5fd90:focus, a.gb-button-13b5fd90:active {
  background-color: #fff !important;
  color: var(--service-accent, #f06120) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #f06120) !important;
}
/* White (stays filled) > accent fill + white ring */
a.gb-button-64db1e83:hover, a.gb-button-64db1e83:focus, a.gb-button-64db1e83:active {
  background-color: var(--service-accent, #f06120) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* ============ f-one-technologies (homepage) ============ */
/* Same Filled>White / White>fill+white-ring hover system as Internet
   Connectivity (user, 2026-09-10), ported to the homepage's buttons.
   The homepage carries no --service-accent (it isn't a service page and
   its buttons are deliberately multi-coloured), so each button inverts
   to its own rest colour rather than one page accent: filled buttons go
   white with their fill colour as text/border/ring; the five service-
   card "Find out more" buttons are handled by the .our-services-slider
   rule further down, which fills each with its card colour under a
   white border+ring. Transparent 2px border reserved at rest so hover
   only recolours it (no layout nudge); !important throughout to beat
   this page's own per-instance generated CSS (8863.css), which loads
   after this file and carries its own light-blue/pink hover swaps. */
a.gb-button-71881eec,
a.gb-button-c431ed7d,
a.gb-button-0f414125,
a.gb-button-bce431c6,
a.gb-button-17604e06,
a.gb-button-6b245ba9,
a.gb-button-3acca46d {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Orange > White: hero "Get in touch", Award Winning Service and the
   three Industries "Find out more" */
a.gb-button-71881eec:hover, a.gb-button-71881eec:focus, a.gb-button-71881eec:active,
a.gb-button-c431ed7d:hover, a.gb-button-c431ed7d:focus, a.gb-button-c431ed7d:active,
a.gb-button-0f414125:hover, a.gb-button-0f414125:focus, a.gb-button-0f414125:active,
a.gb-button-bce431c6:hover, a.gb-button-bce431c6:focus, a.gb-button-bce431c6:active,
a.gb-button-17604e06:hover, a.gb-button-17604e06:focus, a.gb-button-17604e06:active {
  background-color: #fff !important;
  color: var(--primary, #f06120) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--primary, #f06120) !important;
}
/* Blue > White: Cloud Phone Systems "Find out more" */
a.gb-button-6b245ba9:hover, a.gb-button-6b245ba9:focus, a.gb-button-6b245ba9:active {
  background-color: #fff !important;
  color: var(--blue, #76C0FF) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--blue, #76C0FF) !important;
}
/* Navy > White: "Read our Google reviews" under Client Feedback */
a.gb-button-3acca46d:hover, a.gb-button-3acca46d:focus, a.gb-button-3acca46d:active {
  background-color: #fff !important;
  color: var(--secondary, #004269) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--secondary, #004269) !important;
}

/* ============ wifi-and-networking ============ */
/* Same Blue>White / White(fill)>accent+white-ring hover system as Cloud
   Phone Systems, ported to this page's own buttons and accent colour.
   Transparent 2px border reserved at rest so hover only recolours it
   (no layout nudge); !important throughout to beat this page's own
   per-instance generated CSS, which loads after this file. */
a.gb-button-424478e8,
a.gb-button-a5ae33cb,
a.gb-button-3d7dd445,
a.gb-button-958fe207,
a.gb-button-ccece3b5,
a.gb-button-13b5fd90,
a.gb-button-c4fee099,
a.gb-button-6883640f {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Blue > White */
a.gb-button-424478e8:hover, a.gb-button-424478e8:focus, a.gb-button-424478e8:active,
a.gb-button-a5ae33cb:hover, a.gb-button-a5ae33cb:focus, a.gb-button-a5ae33cb:active,
a.gb-button-3d7dd445:hover, a.gb-button-3d7dd445:focus, a.gb-button-3d7dd445:active,
a.gb-button-958fe207:hover, a.gb-button-958fe207:focus, a.gb-button-958fe207:active,
a.gb-button-ccece3b5:hover, a.gb-button-ccece3b5:focus, a.gb-button-ccece3b5:active,
a.gb-button-13b5fd90:hover, a.gb-button-13b5fd90:focus, a.gb-button-13b5fd90:active {
  background-color: #fff !important;
  color: var(--service-accent, #FFCE00) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #FFCE00) !important;
}
/* White (stays filled) > accent fill + white ring */
a.gb-button-c4fee099:hover, a.gb-button-c4fee099:focus, a.gb-button-c4fee099:active,
a.gb-button-6883640f:hover, a.gb-button-6883640f:focus, a.gb-button-6883640f:active {
  background-color: var(--service-accent, #FFCE00) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* ============ mobile-sim-plans ============ */
/* Same Blue>White / White(fill)>accent+white-ring hover system as Cloud
   Phone Systems, ported to this page's own buttons and accent colour.
   Transparent 2px border reserved at rest so hover only recolours it
   (no layout nudge); !important throughout to beat this page's own
   per-instance generated CSS, which loads after this file. */
a.gb-button-424478e8,
a.gb-button-f0601d23,
a.gb-button-36597eeb,
a.gb-button-13b5fd90,
a.gb-button-f191adbb {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Blue > White */
a.gb-button-424478e8:hover, a.gb-button-424478e8:focus, a.gb-button-424478e8:active,
a.gb-button-f0601d23:hover, a.gb-button-f0601d23:focus, a.gb-button-f0601d23:active,
a.gb-button-36597eeb:hover, a.gb-button-36597eeb:focus, a.gb-button-36597eeb:active,
a.gb-button-13b5fd90:hover, a.gb-button-13b5fd90:focus, a.gb-button-13b5fd90:active {
  background-color: #fff !important;
  color: var(--service-accent, #24D19C) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #24D19C) !important;
}
/* White (stays filled) > accent fill + white ring */
a.gb-button-f191adbb:hover, a.gb-button-f191adbb:focus, a.gb-button-f191adbb:active {
  background-color: var(--service-accent, #24D19C) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* ============ it-essentials ============ */
/* Same Blue>White / White(fill)>accent+white-ring hover system as Cloud
   Phone Systems, ported to this page's own buttons and accent colour.
   Transparent 2px border reserved at rest so hover only recolours it
   (no layout nudge); !important throughout to beat this page's own
   per-instance generated CSS, which loads after this file. */
a.gb-button-424478e8,
a.gb-button-e51f3077,
a.gb-button-ff2ed986,
a.gb-button-35837cdd,
a.gb-button-b7e6f602,
a.gb-button-d237b173,
a.gb-button-9526648b,
a.gb-button-13b5fd90,
a.gb-button-ff6e1240,
a.gb-button-d6cbc4b1 {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* Blue > White */
a.gb-button-424478e8:hover, a.gb-button-424478e8:focus, a.gb-button-424478e8:active,
a.gb-button-e51f3077:hover, a.gb-button-e51f3077:focus, a.gb-button-e51f3077:active,
a.gb-button-ff2ed986:hover, a.gb-button-ff2ed986:focus, a.gb-button-ff2ed986:active,
a.gb-button-35837cdd:hover, a.gb-button-35837cdd:focus, a.gb-button-35837cdd:active,
a.gb-button-b7e6f602:hover, a.gb-button-b7e6f602:focus, a.gb-button-b7e6f602:active,
a.gb-button-d237b173:hover, a.gb-button-d237b173:focus, a.gb-button-d237b173:active,
a.gb-button-9526648b:hover, a.gb-button-9526648b:focus, a.gb-button-9526648b:active,
a.gb-button-13b5fd90:hover, a.gb-button-13b5fd90:focus, a.gb-button-13b5fd90:active {
  background-color: #fff !important;
  color: var(--service-accent, #D5ACF8) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #D5ACF8) !important;
}
/* White (stays filled) > accent fill + white ring */
a.gb-button-ff6e1240:hover, a.gb-button-ff6e1240:focus, a.gb-button-ff6e1240:active,
a.gb-button-d6cbc4b1:hover, a.gb-button-d6cbc4b1:focus, a.gb-button-d6cbc4b1:active {
  background-color: var(--service-accent, #D5ACF8) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* ============ pages with no service accent ============ */
/* Simon, 2026-09-23: "Contact us page wrong button hover behaviour on
   hero banner and contact form", "some buttons on orange/blue themed
   pages are now showing as purple", "should be orange and the hover to
   clear". Every family block above relies on --service-accent being set
   on <body>; the pages with no accent -- /contact-us/, About Us,
   Careers, the Customer Area, Awards and the eleven industry pages --
   fell through to two wrong places. A class also listed in a family
   block took that family's FALLBACK colour (the phone pill 13b5fd90
   hovered IT Essentials' purple, the last block in the file), and a
   class in no block kept whatever hover WordPress exported for it (dark
   grey on "Get in touch", blue on the Customer Area's downloads).

   Same two patterns as the family blocks, driven by --pill, the pill's
   own rest colour: Filled > White (white fill, --pill text, 2px
   currentColor border, 1px --pill ring) and White > --pill fill + white
   ring. --pill is the site orange unless a class says otherwise below,
   and --service-accent is set to it ON THESE ELEMENTS ONLY, so the
   family blocks' var(--service-accent, ...) resolve to the right colour
   here too (13b5fd90, a5ae33cb) without touching any other
   var(--service-accent) on the page -- heading dots, the socials rail
   and .has-accent-color keep their own fallbacks. The class -> colour
   map is the rest colour each class actually renders on these pages
   (audited across all 56 of them on 2026-09-23); a5ae33cb is blue on
   most industry pages but orange on Careers, green on Dental, magenta
   on Doctors and pink on Estate Agencies, General Office and Golf
   Clubs, so those are keyed by page. The border is reserved at rest so
   nothing moves on hover. */
body:not([style*="--service-accent"]) :is(
  a.gb-button-198eeb3b, a.gb-button-1f1895d6, a.gb-button-20c5655d, a.gb-button-346811d8,
  a.gb-button-8a47fe41, a.gb-button-9f854ee6, a.gb-button-c638dfe2, a.gb-button-13b5fd90,
  a.gb-button-a5ae33cb, a.gb-button-45bc2c11, a.gb-button-4f7ed94a, a.gb-button-6e69d1f7,
  a.gb-button-bfbcaa45, a.gb-button-340a85e4, a.gb-button-5b612436, a.gb-button-43a0a727,
  a.gb-button-03592781, a.gb-button-522c9106, a.gb-button-52467db6, a.gb-button-7ec1a8d0,
  a.gb-button-65de39ee, a.gb-button-a4127de0, a.gb-button-e80c935e
) {
  --pill: var(--primary, #f06120);
  --service-accent: var(--pill);
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
/* the industry pages' own palette */
body:not([style*="--service-accent"]) :is(
  a.gb-button-45bc2c11, a.gb-button-4f7ed94a, a.gb-button-6e69d1f7, a.gb-button-bfbcaa45,
  a.gb-button-03592781, a.gb-button-522c9106, a.gb-button-52467db6, a.gb-button-7ec1a8d0
) { --pill: var(--blue, #76C0FF); }
body[style*="--site-phone-color"] a.gb-button-a5ae33cb { --pill: var(--blue, #76C0FF); }
body:not([style*="--service-accent"]) :is(a.gb-button-340a85e4, a.gb-button-5b612436, a.gb-button-a4127de0) { --pill: var(--yellow, #FFCE00); }
body:not([style*="--service-accent"]) :is(a.gb-button-43a0a727, a.gb-button-65de39ee) { --pill: var(--pink, #CC289C); }
body:not([style*="--service-accent"]) a.gb-button-e80c935e { --pill: var(--secondary, #004269); }
body.page-dental-practices a.gb-button-a5ae33cb { --pill: #2ACC63; }
body.page-doctors-surgeries a.gb-button-a5ae33cb { --pill: #CC299C; }
body:is(.page-estate-agencies, .page-general-office, .page-golf-clubs) a.gb-button-a5ae33cb { --pill: var(--pink, #CC289C); }
/* Filled > White. 13b5fd90 and a5ae33cb are here as well as in the family
   blocks: the reserved-border rule above outranks a family hover on
   specificity, so without their own hover here the 2px border would
   stay transparent and only the ring would show. */
body:not([style*="--service-accent"]) :is(
  a.gb-button-198eeb3b, a.gb-button-1f1895d6, a.gb-button-20c5655d, a.gb-button-346811d8,
  a.gb-button-8a47fe41, a.gb-button-9f854ee6, a.gb-button-c638dfe2, a.gb-button-13b5fd90, a.gb-button-a5ae33cb,
  a.gb-button-45bc2c11, a.gb-button-4f7ed94a, a.gb-button-6e69d1f7, a.gb-button-bfbcaa45,
  a.gb-button-340a85e4, a.gb-button-5b612436, a.gb-button-43a0a727
):is(:hover, :focus, :active) {
  background-color: #fff !important;
  color: var(--pill) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--pill) !important;
}
/* White > fill + white ring */
body:not([style*="--service-accent"]) :is(
  a.gb-button-03592781, a.gb-button-522c9106, a.gb-button-52467db6, a.gb-button-7ec1a8d0,
  a.gb-button-65de39ee, a.gb-button-a4127de0, a.gb-button-e80c935e
):is(:hover, :focus, :active) {
  background-color: var(--pill) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

/* "The Basics" heading previously had its text force-coloured to the
   accent (overriding the WP "black" text preset). Reverted to match
   "Mesh Networking" on WiFi & Networking -- and most other headings
   site-wide -- which just use the native has-text-black-color preset
   (#363636) with only the trailing "." carrying the accent colour via
   the general heading-dot rule above. One consistent heading style
   instead of singling this one out. */

/* "Nationwide Coverage" on Mobile SIM Plans has its own per-instance
   generated CSS (static/css/generated/205.css) authoring the whole
   heading text green, not just the dot -- same mismatch as the old
   "The Basics", so it gets the same fix: force the text back to the
   standard dark grey and let only the dot (already accent-coloured via
   the general rule above) carry the page's colour. !important needed
   since 205.css loads after this file. */
.gb-headline-22fa65d8 { color: var(--wp--preset--color--text-black, #363636) !important; }

/* Superseded on 2026-09-24 (Simon: "some of the pages are showing grey
   heading text instead of their coloured theme"): on a themed page every
   section heading takes the page colour, as the house pages and Cloud
   Phone Systems already did through has-accent-color. The WordPress-built
   service and product pages set their headings' text with the
   has-text-black-color preset (#363636 !important in brand.css) and only
   the dot in the colour -- "Key Features." on every product page,
   "Superfast FTTP." and "Let's Talk." on Internet Connectivity, "Mesh
   Networking.", "Network Support." and "Networking Hardware." on WiFi &
   Networking -- so those read grey while their neighbours read blue,
   orange or yellow. (0,3,1) + !important outranks the preset's (0,1,0)
   + !important. A heading set this way only ever sits on a light
   background (grey on a coloured band would already have been
   unreadable), so no band exception is needed. "Nationwide Coverage" on
   Mobile SIM Plans, whose text is authored green and was forced to grey
   just above, goes the same way. */
body[style*="--service-accent"] :is(h1, h2, h3) > mark.has-text-black-color { color: var(--service-accent) !important; }
body[style*="--service-accent"] .gb-headline-22fa65d8 { color: var(--service-accent) !important; }
/* "Key Features." on the T44W, T54W, T57W and T58W Pro pages was exported
   with its text bare in the h2 (only the dot in a mark), so the mark rule
   above doesn't reach it. Left grey on purpose (Simon, 2026-09-24: "the
   still-grey Key Features headings can stay as is"). */

/* Every accordion (the site's generic .gb-accordion__toggle component --
   "SmartVoice Messaging" on Cloud Phone Systems, spec/FAQ lists on the
   individual product pages under each service, etc.) reuses the same
   markup, which defaults to purple text regardless of which service
   the page belongs to. Originally scoped to .the-basics-accordian
   (Cloud Phone Systems' own instance) only; generalised to
   body[style*="--service-accent"] so it covers every accordion on
   every page that carries a page_theme_color -- each still picks up
   its own colour via var(--service-accent), and pages with no theme
   colour at all (body has no inline style) are untouched. */
body[style*="--service-accent"] .gb-accordion__toggle {
  color: var(--text-black, #363636) !important;
}
/* Colon-style accent dot after each item's label, matching the heading
   dot pattern elsewhere on the page -- generated via ::after rather
   than edited into the source content. */
body[style*="--service-accent"] .gb-accordion__toggle .gb-button-text::after {
  content: ".";
  color: var(--service-accent);
}
/* Hover highlights the whole row (icon included, via currentColor) in
   the accent colour, and staying open keeps that same colour instead
   of reverting once you've clicked in -- :is() so both states share
   one declaration. */
body[style*="--service-accent"] :is(.gb-accordion__toggle:hover, .gb-accordion-item.is-open > .gb-accordion__toggle, .gb-accordion-item.is-open > .gb-inside-container > .gb-accordion__toggle) {
  color: var(--service-accent) !important;
}
/* The "Three Licences, Mixed to Suit" accordion on Elevate Phone System
   only (Simon, 2026-09-24): the same hover as every other accordion --
   text in the page colour -- and the same when a row holds focus, with
   no grey. theme.css's blanket button:focus { background: #404040 }
   showed as a dark grey row on whichever licence had just been clicked,
   because the site's :hover rule above covers hover only, so the grey
   appeared the moment the pointer left a focused row. The id outranks
   every toggle rule above, !important included. */
#three-licences-mixed-to-suit .gb-accordion__toggle:is(:hover, :focus, :active) {
  background: var(--text-white) !important;
  border-color: transparent !important;
  color: var(--service-accent, var(--secondary)) !important;
}

/* ---------- responsive visibility ---------- */
@media (max-width: 767px) { .hide-on-mobile { display: none !important; } }
@media (min-width: 768px) and (max-width: 991px) { .hide-on-tablet { display: none !important; } }
@media (min-width: 992px) { .hide-on-desktop { display: none !important; } }

/* ================= SITE HEADER (matched to the live theme's real CSS) ================= */
/* the theme sets `body, html { overflow-x: hidden }`, which breaks position:sticky
   in most browsers -- the live site works around this with position:fixed, so we
   match that and pad body by the header's height instead */
/* No body offset for the fixed header -- live doesn't have one either. Page
   content starts at y=0 and slides under the header, and each hero's own top
   padding (150px on the GB containers) provides the clearance. Padding the body
   as well double-counted the header and pushed every page down ~60px: the
   homepage hero sat 155px below the header instead of live's 95px.
   The two templates that are ours rather than migrated -- .blog-header and
   .post-header -- carry the 60px themselves instead. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  background: var(--text-white);
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 60px;
  padding: 0 calc(max((100vw - 1100px) / 2, 1rem));
  box-shadow: 0 1px 6px rgba(0,0,0,.08);
}
.site-branding { flex-shrink: 0; margin-right: 1.5rem; }
.site-branding svg { display: block; }
.main-navigation { flex: 1 1 auto; min-width: 0; }
.main-navigation ul.menu { list-style: none; margin: 0; padding: 0; display: flex; gap: 1rem; height: 60px; }
/* Desktop: the options sit centred in the space between the logo and the
   phone number rather than hugging the logo (user, 2026-09-03). The panels
   are unaffected: Services spans the header, the sections anchor to their
   own item wherever it lands. */
}
.main-navigation ul.menu li { display: flex; align-items: center; position: relative; cursor: pointer; }
/* Live equivalent is `.desktop-navigation > ul > li > a` in wp-custom-css:
   deep blue at 16px, going bold (not orange) on hover. */
.main-navigation ul.menu > li > a {
  display: flex;
  align-items: center;
  height: 60px;
  text-decoration: none;
  color: var(--brand-nav-link);
  font-weight: 400;
  font-size: 16px;
  white-space: nowrap;
}
.main-navigation ul.menu > li:hover > a { font-weight: 700; }
/* Bold is wider than regular, so the hover above used to widen the link and
   shove its neighbours along the bar (user, 2026-09-10). Reserve the bold
   width up front: a hidden bold copy of the label (data-label, nav.html)
   sizes the box and the visible text sits centred inside it, so nothing
   moves on hover. Desktop only -- below 1025px these links are hidden in
   favour of the card stack. */
@media (min-width: 1025px) {
  .main-navigation ul.menu > li > a[data-label] {
    flex-direction: column;
    justify-content: center;
  }
  .main-navigation ul.menu > li > a[data-label]::after {
    content: attr(data-label);
    font-weight: 700;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    pointer-events: none;
  }
}
.main-navigation ul.menu > li.current-menu-item > a { color: var(--brand-nav-link-active); }
/* Services mega-menu -- "Floating Cards": five glass tiles side by side, each
   its own accordion. Hovering or focusing a card expands it in place to
   reveal its sub-links while the row spotlights it and dims its neighbours.
   Pure CSS (:hover/:focus-within/:has) -- no tab-switching JS involved. */
.mega-services { position: relative; --mega-w: 980px; }
/* Unifying fix: theme.css ships a global `a:focus { outline: thin
   dotted; }`, and its (0,1,1) specificity beats any single-class rule of
   ours, so a plain `.mega-whatever:focus { outline: none }` never
   actually wins. On top of that, Chromium/WebKit adds its own default
   tap-highlight on any <a>. Between the two, every link in the dropdown
   -- cards, child items, CTAs -- shows a stray focus/tap box. Scoping to
   `.mega-menu a`, the one class every redesign shares, kills it in one
   place instead of patching each link selector piecemeal (replaces the
   narrower .mega-float-main/.mega-float-drop li a patches). */
.mega-menu a:focus,
.mega-menu a:focus-visible,
.mega-menu a:active {
  outline: none !important;
  box-shadow: none !important;
  -webkit-tap-highlight-color: transparent !important;
}

/* The panel is offset 14px below the nav item, so travelling from "Services"
   down to the options crosses a strip that belongs to neither element -- hover
   is lost mid-journey and the menu snaps shut. This invisible bridge spans that
   strip across the panel's full width, keeping :hover alive on .mega-services
   while the cursor crosses. It only exists while the menu is open, so it never
   sits over the page intercepting clicks. */
.mega-services:hover::after,
.mega-services.is-hover::after,
.mega-services:focus-within::after {
  content: "";
  position: absolute;
  top: 100%;
  left: -1.5rem;
  width: var(--mega-w);
  max-width: calc(100vw - 2rem);
  height: 16px;
}

.mega-menu {
  display: flex;
  position: absolute;
  top: calc(100% + 14px);
  left: -1.5rem;
  width: var(--mega-w);
  max-width: calc(100vw - 2rem);
  background: var(--text-white);
  border-radius: 20px;
  box-shadow: 0 24px 48px -12px rgba(0, 33, 53, .28), 0 0 0 1px rgba(0, 33, 53, .04);
  z-index: 50;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px) scale(.98);
  transform-origin: top left;
  transition: opacity .22s ease, transform .22s cubic-bezier(.2,.8,.2,1), visibility .22s;
  pointer-events: none;
}
/* `.is-hover` is held by main.js for a moment after the cursor leaves, which is
   what lets you travel from "Services" to the panel. CSS :hover alone cannot do
   this: the nav item is only ~65px wide, so any diagonal towards the panel exits
   it sideways -- passing over the header and page, neither of which is a
   descendant -- before the panel is reached. */
.mega-services:hover .mega-menu,
.mega-services.is-hover .mega-menu,
.mega-services:focus-within .mega-menu,
.mega-services.is-open .mega-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.mega-arrow { display: none; }
/* main.js adds this for one frame while swapping panels along the banner
   so the outgoing and incoming panels switch instantly (no cross-fade) */
.mega-services.is-switching .mega-menu { transition: none !important; }

/* Stretches the panel to the header's own content width -- from the F One
   logo to the right edge of "Get in touch" -- instead of the ~980px box
   the base .mega-menu anchors under the "Services" link. That needs
   `position: fixed` (not the base rule's absolute, which is relative to
   .mega-services -- only ~65px wide and nowhere near centred): `left`/
   `right` reuse the header's own `calc(max((100vw - 1100px) / 2, 1rem))`
   inset, so the panel's edges track the logo and button at any viewport
   width the same way the header's own padding does. `top: 74px` matches
   the header's 60px height plus the usual 14px gap.
   Hover still works unchanged: an ancestor's :hover (and .mega-services's
   mouseenter/mouseleave in main.js) is driven by DOM containment, not
   visual position, so a fixed-position descendant still counts. */
.mega-menu--floating {
  position: fixed;
  top: 74px;
  left: calc(max((100vw - 1100px) / 2, 1rem) - 8px);
  right: calc(max((100vw - 1100px) / 2, 1rem) - 8px);
  width: auto;
  max-width: none;
  background: linear-gradient(160deg, #ffffff 0%, #f2f5f8 100%);
  padding: 22px;
  overflow: visible;
}
.mega-float-row { display: flex; gap: 12px; align-items: flex-start; width: 100%; }
.mega-float-card {
  flex: 1 1 0;
  min-width: 0;
  background: rgba(0, 33, 53, .025);
  border: 1px solid rgba(0, 33, 53, .08);
  border-radius: 16px;
  position: relative;
  overflow: hidden;
  transition: flex-grow .32s cubic-bezier(.2,.8,.2,1), transform .32s cubic-bezier(.2,.8,.2,1), border-color .25s ease, background-color .25s ease, box-shadow .25s ease, opacity .25s ease, filter .25s ease;
}
.mega-float-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--card-color);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .25s ease;
}
/* Desktop-only: a touch tap leaves :hover stuck on the tapped card (no
   pointer ever leaves), so below 1025px these would fight the tap-driven
   .is-open state -- a closed card stayed expanded, the open one dimmed. */
@media (min-width: 1025px) {
.mega-float-card:hover,
.mega-float-card:focus-within {
  flex-grow: 1.35;
  background: var(--text-white);
  border-color: rgba(0, 33, 53, .16);
  box-shadow: 0 18px 36px -14px rgba(0, 33, 53, .28);
  transform: translateY(-3px);
}
/* IT Essentials is always last in service_items (nav.yaml order) and
   carries the longest label in the whole menu ("Cyber Essentials
   Certification Support"), so it gets a bit more room on expand than
   the other four cards -- less than before now that "Remote Monitoring
   and Management (RMM)" lost its "(RMM)" suffix and is no longer the
   widest line. */
.mega-float-card:last-child:hover,
.mega-float-card:last-child:focus-within {
  flex-grow: 1.515;
}
.mega-float-card:hover::before,
.mega-float-card:focus-within::before { transform: scaleX(1); }
.mega-float-row:has(.mega-float-card:hover) .mega-float-card:not(:hover),
.mega-float-row:has(.mega-float-card:focus-within) .mega-float-card:not(:focus-within) {
  opacity: .5;
  filter: saturate(.6);
}
}
.mega-float-main {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 14px;
  text-decoration: none;
  min-width: 0;
}
/* NOTE: on desktop theme.css's `.main-navigation a { display: block }`
   (0,1,1) outranks the `display: flex` above (0,1,0), so the icon (a
   flex-level span) sits on its own line ABOVE the title. That is the
   chosen desktop look -- the title then fits on one line in a ~200px
   card, where a side-by-side row forced "Internet Connectivity" and
   "Cloud Phone Systems" onto two lines (tried 2026-09-02 and reverted).
   Mobile restates flex at (0,2,0) in the <=1024px block for a compact row. */
/* Shifted the same 4px as the heading text below it, so the icon lines
   up with the heading and the child items rather than sitting 4px to
   their left. */
.mega-float-icon { display: flex; width: 30px; height: 30px; flex-shrink: 0; margin-left: 4px; }
.mega-float-icon img { width: 100%; height: 100%; object-fit: contain; }
/* Our Partners card: five partner circles side by side, not overlapped
   (Simon, 2026-09-18). */
.mega-float-icon--stack { width: auto; gap: 6px; }
.mega-float-icon--stack img { width: 30px; height: 30px; border-radius: 50%; }   /* the same 30px as every other card's circle (Simon, 2026-09-18) */
/* 4px so the heading's own text lines up with the child items below it
   (their <a> carries `padding: 6px 4px`, so their text sits 4px in from
   the card edge -- the heading had no equivalent inset). */
.mega-float-title { flex: 1; min-width: 0; padding-left: 4px; color: var(--secondary); font-weight: 700; font-size: .88rem; line-height: 1.25; }
.mega-float-chevron {
  color: var(--card-color);
  flex-shrink: 0;
  transition: transform .25s ease;
}
@media (min-width: 1025px) {
.mega-float-card:hover .mega-float-chevron,
.mega-float-card:focus-within .mega-float-chevron { transform: rotate(180deg); }
}
/* Animates to the content's own measured height via the CSS grid
   `0fr -> 1fr` row trick, instead of guessing a fixed max-height (was
   480px) and animating toward that ceiling regardless of how tall the
   content actually is. A fixed target overshoots short lists and, worse,
   fights the card's simultaneous width transition: as the card widens
   the text reflows and its true height changes mid-animation, but
   max-height keeps easing toward the same unrelated 480px -- the
   mismatch between the two is what read as a "bounce". grid-template-rows
   tracks the real row size continuously as it changes, so there's
   nothing to overshoot. */
.mega-float-drop {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  padding: 0 14px;
  transition: grid-template-rows .32s cubic-bezier(.2,.8,.2,1), opacity .22s ease, padding .32s ease;
}
/* v17 swing-drilldown: height is JS-managed (main.js resizeDropInner) so the
   card can smoothly grow/shrink to whatever depth is currently showing --
   see the .mega-float-nested-drop block below for the rest of the pattern. */
.mega-float-drop-inner {
  position: relative;
  overflow: hidden;
  min-height: 0;
  transition: height .32s cubic-bezier(.2,.8,.2,1);
}
@media (min-width: 1025px) {
.mega-float-card:hover .mega-float-drop,
.mega-float-card:focus-within .mega-float-drop {
  grid-template-rows: 1fr;
  opacity: 1;
  padding: 0 14px 16px;
}
}
/* theme.css's `.main-navigation ul ul { position:absolute; left:-999em;
   box-shadow:0 3px 3px rgba(0,0,0,.2); }` (the WP default that hides a
   submenu off-canvas until hovered directly, and drop-shadows it once
   revealed) outranks a plain class selector on specificity -- (0,1,2) vs
   this rule's (0,1,1) -- and still catches this list, since it's a ul
   nested in ul.menu regardless of the wrappers in between. Without these
   !important overrides every child link renders ~999em off to the left,
   the box-shadow traces a faint box around the whole list even once
   position is fixed, and (display, added after the mobile tap-to-expand
   behaviour below surfaced it) the same specificity gap means theme.css's
   *other* `@media (max-width: 1024px) { .main-navigation ul ul {
   display: none } }` rule wins there too -- every card's sub-item list
   stayed hidden even once the card itself correctly expanded, leaving
   only the "View all" link inside it visible. */
.mega-float-drop ul {
  position: static !important;
  left: auto !important;
  top: auto !important;
  float: none !important;
  box-shadow: none !important;
  /* theme.css's mobile slide-in (`.main-navigation.is-open ul { transform:
     translateY(0) }`, <=1024px) reaches every ul in the nav. Even an
     identity transform makes the ul the containing block for its
     position:absolute descendants, so each .mega-float-nested-drop
     anchored to its parent *list* (below that panel's back row) instead
     of the panel it's meant to cover, stacking back rows and clipping
     the bottom of any third-level list. */
  transform: none !important;
  list-style: none;
  margin: 0;
  padding: 10px 0 0;
  border-top: 1px solid rgba(0, 33, 53, .08);
  display: flex !important;
  flex-direction: column;
  gap: 1px;
}
.mega-float-drop li a {
  display: block;
  padding: 6px 4px;
  border-radius: 6px;
  color: var(--text-black) !important;
  text-decoration: none;
  font-size: .78rem;
  font-weight: 500;
  transition: background-color .15s ease, color .15s ease, transform .15s ease;
}
/* theme.css carries `.main-navigation li:hover > a { color: #f06120; }`
   (direct-child, not just `a:hover`) which ties this file's selectors on
   raw specificity -- (0,2,2) either way -- so which one wins came down to
   source order, and evidently not reliably in our favour. `!important`
   here and on the :hover rule below settles it outright regardless of
   specificity or order.

   The shift-right-on-hover uses `transform: translateX()`, not
   `padding-left` -- padding changes the element's own content-box width,
   which for the longest label in the menu ("Microsoft 365 License
   Management") could force its flex-sized card to recalculate/reflow
   abruptly instead of animating smoothly. transform is purely visual
   (GPU-composited), so it never triggers that reflow. */
/* --item-color (nav.yaml `color`, e.g. each partner's brand colour) wins
   over the card colour when a link carries one */
.mega-float-drop li a:hover {
  color: var(--item-color, var(--card-color)) !important;
  transform: translateX(5px);
}
/* Cloud Phone Systems > Hardware: one nested level inside the existing flat
   child list. Same specificity (0,1,1) as `.mega-float-drop ul` above, so
   source order alone decides -- coming later, this wins for the
   properties it sets, leaving the shared link styling (size/colour/
   hover) on `.mega-float-drop li a` completely untouched, so the nested
   item reads as "one level down" rather than a new visual language.

   `.main-navigation ul.menu li { display:flex; align-items:center;
   position:relative; }` (0,2,2) reaches every li in the mega-menu
   regardless of nesting depth, which turned a parent and its nested list
   into flex-row siblings on the same line instead of stacked rows -- the
   !important restores normal block stacking for this one wrapper.

   `position: static` (v17 swing-drilldown) undoes that same rule's
   `position:relative` for exactly this class. Without it, every li.mega-
   float-nested -- being the *closer* ancestor -- wins the containing-block
   race for its own `.mega-float-nested-drop` over the intended
   `.mega-float-drop-inner`/ancestor-drop stage, so the drop positions
   `inset:0` against its own ~24px trigger row instead of the whole stage
   it's meant to cover. (Elevate happening to sit first in Cloud Phone
   Systems' list hid this initially -- its own li's box starts at the same
   point the stage does, so the bug was invisible until a second level of
   nesting, e.g. Hardware, sat further down its parent's list.) */
.mega-float-nested {
  display: block !important;
  position: static !important;
}
/* Click/tap-to-reveal at every width (main.js). `.mega-float-drop li a`
   (0,1,2) set the link `display:block`; this needs `flex` to align the
   label and chevron on one row, so it's re-scoped one level narrower
   (0,2,2) to win without touching the shared rule's other properties
   (padding/colour/font-size/hover). */
.mega-float-drop li.mega-float-nested > a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.mega-float-nested-chevron {
  flex-shrink: 0;
  opacity: .5;
  color: var(--card-color);
}
/* v17 swing-drilldown: clicking a child with its own children slides its
   list IN from the right, covering the list it lived in -- not an inline
   accordion. `.mega-float-nested-drop` sits `position:absolute` over
   whichever `<ul>` it's nested inside (top level: `.mega-float-drop-inner`,
   which is `position:relative`; any deeper level: the nearest ancestor
   `.mega-float-nested-drop`, itself `position:absolute` and so *also* a
   valid containing block for its own descendants) -- DOM nesting depth
   doesn't matter, only the nearest positioned ancestor does, so this one
   rule covers every depth. Height is deliberately left `auto`/unclipped
   here: only the outermost `.mega-float-drop-inner` clips and animates
   its height (JS-managed, see main.js resizeDropInner), so a short
   intermediate level never truncates a taller one drilled in beneath it. */
/* `z-index: 1` (not the default `auto`) is load-bearing, not decoration.
   theme.css gives every `<li>` in the nav `position: relative`, so each of
   this drop's OWN top-level siblings (CRM Integration, Insights, ...) is
   *also* a `position:relative, z-index:auto` box. Auto-z-index positioned
   siblings stack purely by tree order, and that comparison happens at the
   sibling level regardless of what's nested inside either one -- so
   Elevate's drop, despite being `position:absolute`, would still paint (and
   hit-test) *underneath* any later sibling `<li>` whose own flow box
   happens to overlap it on screen, because that later `<li>` is later in
   tree order. A positive z-index promotes the drop to its own stacking
   context, which always paints after every z-index:auto layer in its
   parent regardless of DOM order -- covering the siblings for real instead
   of just visually beneath them. */
.mega-float-nested-drop {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  background: var(--text-white);
  transform: translateX(100%);
  opacity: 0;
  pointer-events: none;
  transition: transform .32s cubic-bezier(.2,.8,.2,1), opacity .22s ease;
}
.mega-float-nested.is-open > .mega-float-nested-drop {
  transform: translateX(0);
  opacity: 1;
  pointer-events: auto;
}
/* The list a drilled-in panel covers stays in the DOM/flow (so its own
   container's height book-keeping is untouched) but slides left and fades
   as its covering sibling swings in, instead of just vanishing under it.

   This targets each `<a>` individually -- NOT the `<ul>` (or the `<li>`) as
   a whole, even though that reads simpler. `opacity` composites an element
   and its entire subtree as one group: a `<ul opacity:0>` would carry every
   descendant down to zero, INCLUDING the very `.mega-float-nested-drop`
   (opacity:1, sitting a couple of DOM levels deeper inside the `<li>` that's
   opening) this whole interaction exists to reveal -- a child can't opt out
   of an ancestor's opacity the way it can override `visibility`. Fading the
   `<a>` instead leaves `.mega-float-nested-drop` a sibling of the thing
   being faded, never a descendant of it, so it's untouched. (`transform` on
   the `<ul>` had the same failure mode from a different angle: it would
   make the `<ul>` the containing block for its own `position:absolute`
   descendants -- including that same drop -- pulling its `inset:0` off
   `.mega-float-drop-inner` and onto the moving `<ul>` instead.) */
.mega-float-drop-inner > ul > li > a,
.mega-float-nested-drop > ul > li > a {
  transition: background-color .15s ease, color .15s ease, transform .22s cubic-bezier(.2,.8,.2,1), opacity .2s ease;
}
.mega-float-drop-inner > ul:has(> li.mega-float-nested.is-open) > li > a,
.mega-float-nested-drop > ul:has(> li.mega-float-nested.is-open) > li > a {
  transform: translateX(-16px);
  opacity: 0;
  pointer-events: none;
}
.mega-float-nested-drop > ul {
  margin: 0;
  padding: 0;
  border-top: none;
}
/* Small breadcrumb/back row at the top of every drilled-in panel -- click
   (or the left chevron) returns to the list this panel covered. Label is
   the section you're currently inside (its own trigger's label), not a
   bare "Back", so it also orients you while you're a couple of levels deep.

   theme.css's generic `button { background:#f06120; border:1px solid
   #f06120; color:#fff; padding:.6em 1em .4em; }` (plus a `:hover`/`:focus`/
   `:active` variant swapping in #404040) reaches this element -- a plain
   `<button>` -- and its pseudo-class rules (0,1,1) outrank this plain class
   selector (0,1,0), so a click that leaves the button focused would win out
   over an un-`!important`'d override here. `!important` on every property
   theme.css sets settles it regardless of pseudo-state. */
.mega-float-back {
  display: flex !important;
  width: 100%;
  align-items: center;
  gap: 6px;
  margin: 0 0 6px;
  padding: 6px 4px 10px !important;
  border: none !important;
  border-bottom: 1px solid rgba(0, 33, 53, .08) !important;
  border-radius: 0 !important;
  background: none !important;
  color: var(--card-color) !important;
  font: inherit;
  font-weight: 700;
  font-size: .78rem;
  text-align: left;
  cursor: pointer;
}
.mega-float-back-icon { flex-shrink: 0; transition: transform .15s ease; }
.mega-float-back:hover .mega-float-back-icon,
.mega-float-back:focus-visible .mega-float-back-icon { transform: translateX(-3px); }
/* "View all" sits below the top-level list only -- hide it (rather than let
   it get covered) whenever any depth is drilled into, `:has()` reaching
   through however many levels down the open one sits. */
.mega-float-cta { transition: opacity .2s ease, transform .2s ease, gap .18s ease; }
.mega-float-drop-inner:has(.mega-float-nested.is-open) > .mega-float-cta {
  opacity: 0;
  pointer-events: none;
  transform: translateX(-12px);
}
/* theme.css's `.main-navigation a { display:block; color:#535768;
   width:max-content; }` (0,1,1) outranks a plain `.mega-float-cta`
   (0,1,0), so it was silently winning on both display (breaking the
   icon/text flex alignment, since block ignores align-items/gap) and
   colour (stuck at the muted nav grey instead of the card's colour).
   !important on both settles it regardless of specificity. */
.mega-float-cta {
  display: inline-flex !important;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
  padding-left: 4px;
  color: var(--card-color) !important;
  text-decoration: none;
  font-weight: 700;
  font-size: .76rem;
  transition: gap .18s ease;
}
.mega-float-cta:hover { gap: 8px; }
.site-contact { flex-shrink: 0; display: flex; align-items: center; justify-content: flex-end; gap: 1rem; margin-left: 1.5rem; }
/* Live wraps the number in a grey span but the visible text is the link
   inside it, which picks up the theme's orange `a` colour at 14px/400.
   The 16px gap on .site-contact already matches live's padding-right. */
/* `--service-accent` is set inline on <body> only for the 5 service
   pages (build.py's SERVICE_ACCENTS), so var(...,fallback) makes every
   other page fall straight through to the normal site-wide colour. */
.site-phone-number,
.site-phone-number:visited {
  font-weight: 600;   /* semibold, so the digits read as thick as the 2px underline (Simon, 2026-09-18) */
  font-size: 14px;
  /* the page accent where there is one; a themed page with no accent (the
     Industries pages) passes --site-phone-color instead; orange otherwise.
     :visited is named too: theme.css's `a:visited { color: #f06120 }` beats a
     lone class, and Chromium paints visited links a beat after load, so for
     anyone who has ever tapped the number it "loaded the right colour then
     went orange after 2 seconds" (Simon, 2026-09-17). */
  color: var(--service-accent, var(--site-phone-color, var(--brand-link)));
  text-decoration: none;
  white-space: nowrap;
  position: relative;
}
/* hover: an underline in the page colour that grows from the middle of the
   number out to both ends, as the Services card underline does (Simon,
   2026-09-18, replacing the earlier pop). The right inset matches the 1rem
   padding theme.css puts after the number, so the line ends with the digits. */
.site-phone-number::after {
  content: "";
  position: absolute;
  left: 0; right: 1rem; bottom: -3px;
  height: 2px;
  background: var(--service-accent, var(--site-phone-color, var(--brand-link)));
  transform: scaleX(0);
  transform-origin: 50% 50%;
  transition: transform .22s ease;
}
.site-phone-number:hover::after,
.site-phone-number:focus::after { transform: scaleX(1); }
/* theme.css's blanket `a:hover, a:focus, a:active { color: #f06120 }`
   outscores the rest-state rule above (a class+pseudo beats a bare
   class), so the phone number always flashed the site's default orange
   on hover regardless of the page's own accent colour. Restate the same
   colour on hover -- .site-phone-number:hover's two classes beat that
   rule's one. Bold was tried first and looked ugly (a visible
   reflow/thickening next to the steady-weight nav beside it); underline
   was tried next and didn't land either. A soft text-shadow glow came
   next, then a small pop; on 2026-09-18 Simon asked for a centre-out
   underline in the page colour instead (the ::after rule above). The
   colour never changes, so nothing reflows. */
.site-phone-number:hover,
.site-phone-number:focus,
.site-phone-number:active {
  color: var(--service-accent, var(--site-phone-color, var(--brand-link)));
  text-shadow: none;
}
/* theme.css pins radius/padding/background with !important, matching live;
   only the weight needs stating here (live renders this button at 300).
   background-color needs !important of its own too, to beat theme.css's
   own #f06120 !important on the same property. */
.gb-button-wrapper a {
  display: inline-flex;
  background-color: var(--service-accent, var(--brand-btn-bg)) !important;
  color: var(--brand-btn-text);
  text-decoration: none;
  font-weight: 300;
  white-space: nowrap;
  /* Reserves the same 2px the hover rule below uses (0 on non-themed
     pages), so hover only recolours the border instead of growing the
     box and nudging the phone number beside it. */
  border: var(--service-hover-border-w, 0) solid transparent !important;
  transition: background-color .2s ease, border-color .18s ease;
}
/* On the 5 service-themed pages, this header CTA gets the same Blue >
   White hover as the other blue buttons on Cloud Phone Systems: white
   fill, accent text, thick accent border, accent ring+glow. Everywhere
   else --service-hover-bg / --service-accent / --service-hover-border-w
   are all undefined, so every property here falls back to exactly the
   original grey hover with a 0-width (invisible, layout-neutral)
   border -- this rule is a no-op site-wide except on those 5 pages.
   !important throughout: theme.css's deeper
   .site-header .site-contact .gb-button-wrapper a (no :hover) sets
   color/background at (0,3,1), which otherwise beats this (0,2,1)
   selector regardless of file order since specificity is compared
   before source order. */
.gb-button-wrapper a:hover {
  background-color: var(--service-hover-bg, var(--brand-btn-bg-hover)) !important;
  color: var(--service-accent, var(--brand-btn-text)) !important;
  border: var(--service-hover-border-w, 0) solid var(--service-accent, transparent) !important;
  box-shadow: 0 0 0 1px var(--service-accent, transparent) !important;
}
/* On every page without a service theme (the home page, Industries,
   partners, blog...) the header "Get in touch" button hovers exactly like
   the orange buttons on the home page: white fill, orange text, 2px orange
   border and a 1px orange ring, with the border reserved at rest so nothing
   moves. Done by giving the wrapper the three variables the themed pages
   set on <body>, with the Brand Kit orange as the accent, so the two rules
   above do the work; themed pages are excluded and keep their page colour.
   The phone number beside it is a sibling, so it is untouched (Simon,
   2026-09-18). */
body:not([style*="--service-accent"]) .site-header .site-contact .gb-button-wrapper {
  --service-accent: var(--primary, #f06120);
  --service-hover-bg: #fff;
  --service-hover-border-w: 2px;
}
/* theme.css sets the floating socials rail to a flat #f06120; overridden
   here (loads after theme.css) so it also picks up --service-accent on
   the 5 service pages, matching the phone number and "Get in touch"
   button above. */
.f-one-social-buttons { background-color: var(--service-accent, #f06120); }
/* The rail itself already follows the page accent (above); the hover
   tooltip that pops out next to each icon ("View Our Google Reviews"
   etc.) is a separate element in theme.css with its own hardcoded
   #f06120, so it stayed orange on every themed page regardless of the
   rail's colour. */
.f-one-social-buttons .tooltip-text { background-color: var(--service-accent, #f06120); }
.menu-toggle { display: none; cursor: pointer; background: none; border: none; }
/* theme.css's generic `button:hover/:focus/:active { background: #404040 }`
   (0,1,1) outranks the class above and left a dark square behind the
   hamburger after a tap -- invisible on the old navy banner, obvious on
   the white one. */
.menu-toggle:hover,
.menu-toggle:focus,
.menu-toggle:active { background: none !important; border: none !important; }

/* 1024 matches theme.css's own header breakpoint (hamburger, logo swap,
   white link colour all flip at 1025px there). At 991 the two disagreed
   across 992-1024px: theme.css was already in mobile mode with the menu
   translated off-screen, but the hamburger to open it was hidden. */
@media (max-width: 1024px) {
  /* White banner and menu on mobile, matching the desktop header, instead
     of theme.css's navy (#103e62 header, navy gradient menu). !important
     beats theme.css's own header rule; the small logo drops the
     brightness/invert filter theme.css uses to turn it white for navy. */
  .site-header { padding: 0 1rem; background: #fff !important; box-shadow: 0 1px 0 rgba(0, 33, 53, .08); }
  .site-header .site-branding-sm { filter: none !important; }
  .site-branding { width: auto; }
  .site-branding svg path { fill: var(--secondary) !important; }
  .main-navigation { width: auto; position: static; }
  .menu-toggle { display: inline-flex; }
  .main-navigation ul.menu {
    display: none;
    position: fixed;
    inset: 60px 0 0 0;
    height: auto;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: #fff !important;
    padding: 1rem;
    overflow-y: auto;
    z-index: 90;
  }
  .main-navigation.is-open ul.menu { display: flex; }
  /* theme.css gives the open menu `height: 100vh`, but it starts 60px down
     (under the header), so its last 60px -- and the bottom of the final
     card once a tall card above is expanded -- sat below the screen where
     no amount of scrolling could reach them. Let the inset size it. */
  .main-navigation ul.menu, .main-navigation.is-open ul.menu { height: auto !important; max-height: none !important; }
  .main-navigation ul.menu > li { width: 100%; }
  .main-navigation ul.menu > li > a { height: auto; padding: 12px 0; color: var(--secondary); width: 100%; }
  .mega-arrow { display: none; }
  /* no hover bridge on touch layouts -- the panel sits inline and is driven by
     .is-open, so the strip would only overlay content */
  .mega-services:hover::after,
  .mega-services.is-hover::after,
  .mega-services:focus-within::after { content: none; }
  .mega-menu {
    position: static;
    width: 100%;
    max-width: none;
    flex-direction: column;
    box-shadow: none;
    /* no panel chrome on mobile: the cards sit straight on the white menu */
    background: none;
    border: none;
    padding: 0;
    border-radius: 0;
    margin: 6px 0 10px;
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    display: none;
  }
  .mega-services.is-open .mega-menu { display: flex; }
  .mega-services:hover .mega-menu { display: none; }
  .mega-services.is-open:hover .mega-menu { display: flex; }
  .mega-tabs { width: 100%; padding: 10px; background: none; gap: 2px; }
  .mega-tab { padding: 10px; }
  .mega-tab span:not(.mega-tab-icon) { color: var(--text-white); }
  .mega-tab-chevron { display: none; }
  .mega-panels { padding: 0 10px 10px; max-width: none; }
  .mega-panel-head { border-bottom-color: rgba(255,255,255,.3); }
  .mega-panel-head h3 { color: var(--text-white); }
  .mega-panel ul { grid-template-columns: 1fr; }
  .mega-panel li a { color: var(--text-white); }
  .mega-panel li a:hover { background: rgba(255,255,255,.08); color: var(--text-white); }
  .site-contact .site-phone-number { display: none; }

  /* .mega-float-row/-card ("Floating Cards", further up this file) never
     got a mobile treatment when they replaced whatever the .mega-tabs
     rules above were originally written for -- unconditionally
     `display:flex` with no wrap, five cards wide, they ran straight off
     the right edge of a phone screen with every label truncated
     ("Clou", "Inter", "Mob"...). Stacking them is the visible half of the
     fix; the other half is that .mega-float-main is a plain <a> to the
     service's own page, so on a real phone a tap navigated away and every
     child link ("Phone System Basics", "Hardware", ...) was unreachable.
     main.js intercepts a tap on it below 1025px and toggles .is-open on
     the card instead; these rules mirror the desktop reveal under that
     class (the :hover versions are gated to >=1025px, since a tap leaves
     :hover stuck and it would otherwise override the tap state), and the
     "View all" link inside .mega-float-drop covers the navigation
     .mega-float-main would otherwise have done directly. */
  .mega-float-row { flex-direction: column; gap: 8px; }
  .mega-float-card { width: 100%; flex: none; }
  /* theme.css's `.main-navigation a { display:block; width:max-content }`
     (0,1,1) beats `.mega-float-main`'s own `display:flex` (0,1,0) -- kept
     that way on desktop (icon above title, see the note there), but here
     restated at (0,2,0): icon and title side by side, full width so the
     whole row is one target, tighter padding -- ~64px per card. */
  .main-navigation .mega-float-main { display: flex; width: 100%; padding: 12px 14px; }
  .mega-float-card.is-open {
    background: var(--text-white);
    border-color: rgba(0, 33, 53, .16);
  }
  .mega-float-card.is-open::before { transform: scaleX(1); }
  .mega-float-card.is-open .mega-float-chevron { transform: rotate(180deg); }
  .mega-float-card.is-open .mega-float-drop {
    grid-template-rows: 1fr;
    opacity: 1;
    padding: 0 14px 16px;
  }
  /* theme.css lays every nav li out as a centred flex ROW (`.main-navigation
     li { display:flex; justify-content:center }`), which put the "Services"
     label *beside* the card stack -- squeezed into a narrow left column
     with the cards filling the rest -- instead of above it, and centred
     every child link inside a card. Selectors carry enough specificity to
     beat that rule outright rather than relying on file order. */
  .main-navigation ul.menu > li.mega-services { flex-direction: column; align-items: stretch; }
  /* No "Services" heading on mobile: main.js opens the card panel as soon
     as the menu does, so the heading only duplicated what the cards show
     and cost a row of screen. The panel starts flush at the top instead. */
  .main-navigation ul.menu > li.mega-services > a { display: none; }
  .mega-services .mega-menu { margin-top: 0; }
  .mega-float-drop ul > li { justify-content: flex-start; }
  /* Full-width rows and roomier padding: the desktop list is sized for a
     pointer (~24px rows); these are finger targets. */
  .mega-float-drop li a { width: 100%; padding: 11px 6px; font-size: .92rem; }
  .mega-float-back { padding: 10px 6px 12px !important; font-size: .9rem; }
  .mega-float-cta { padding: 8px 6px; font-size: .88rem; }
}

/* ================= homepage "Products & Services" carousel =================
   Refresh of the five brand-coloured slide cards (.our-services-slider, the
   Slick carousel on f-one-technologies.md). Markup is untouched -- the
   GenerateBlocks containers/headline/button ids are still what the
   generated CSS (generated/8863.css) targets -- so everything here wins on
   specificity, not load order: generated/*.css, wp-custom.css and
   carousel.css all load AFTER this file.

   Height: the generated CSS gives every card `height: 400px`, but
   carousel.css's `.wp-block-cb-carousel .slick-slide > div { height: 100% }`
   (0,2,1) beats that (0,1,0) and resolves against Slick's auto-height slide
   -- i.e. to the card's own content -- so the card with the longest
   paragraph (Internet Connectivity, 3 lines) ran 24px taller than the other
   four. A shared min-height sets the standard here; main.js then measures
   the tallest card after Slick lays out (and on every resize/breakpoint)
   and gives all of them that min-height, so copy that outgrows the
   standard at a narrow width still leaves every card the same size.

   Layout: the .gb-inside-container becomes a 2-column grid so the 150px
   stacked icon becomes a 64px badge with the heading to its right, the
   paragraph spans below, and the button is pinned to the bottom edge
   regardless of paragraph length. */
.our-services-slider .wp-block-cb-slide.slick-slide {
  display: flex;
  flex-direction: column;
  padding: 36px 12px;
}
.our-services-slider .wp-block-cb-slide > .gb-container {
  flex: 1 1 auto;
  width: 100%;
  height: auto;
  min-height: 340px;
  padding: 28px;
  border-radius: 20px;
  justify-content: flex-start;
  /* brand colour still comes from the generated background-color; this
     gradient sits over it for a little depth instead of a flat fill */
  background-image: linear-gradient(150deg, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, 0) 45%, rgba(0, 33, 53, .14) 100%);
  /* soft offset shadow + hairline inner highlight, replacing the dated
     black halo (0 0 12px 2px rgba(0,0,0,.5)) */
  /* no shadow (or inset ring): the user wants plain solid cards on every
     screen size -- the hover lift below is the only depth cue */
  box-shadow: none;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), box-shadow .3s ease;
}
.our-services-slider .wp-block-cb-slide > .gb-container:hover {
  transform: translateY(-4px);
  box-shadow: none;
}
.our-services-slider .wp-block-cb-slide .gb-inside-container {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "icon title"
    "text text"
    "btn  btn";
  column-gap: 16px;
  row-gap: 16px;
  align-items: center;
  width: 100%;
  /* fills the card via flex, not `height:100%` -- a percentage can't
     resolve against the card's min-height, so the 1fr text row never grew
     and the button sat under the paragraph instead of on the bottom edge */
  flex: 1 1 auto;
  align-self: stretch;
  height: auto;
}
.our-services-slider .wp-block-cb-slide .gb-inside-container > figure {
  grid-area: icon;
  margin: 0;
  width: 64px;
  height: 64px;
}
/* the img carries an inline style="width:150px" from the block editor */
.our-services-slider .wp-block-cb-slide .gb-inside-container > figure img {
  width: 64px !important;
  height: 64px;
  object-fit: contain;
  filter: drop-shadow(0 4px 8px rgba(0, 33, 53, .18));
}
.our-services-slider .wp-block-cb-slide .gb-inside-container > h2 {
  grid-area: title;
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.15;
}
.our-services-slider .wp-block-cb-slide .gb-inside-container > p {
  grid-area: text;
  align-self: start;
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
  opacity: .92;
}
.our-services-slider .wp-block-cb-slide .gb-inside-container > a {
  grid-area: btn;
  align-self: end;
  justify-self: start;
  margin: 0;
  box-shadow: 0 6px 14px -8px rgba(0, 33, 53, .45);
  transition: transform .2s ease, box-shadow .2s ease, background-color .2s ease, color .2s ease;
}
.our-services-slider .wp-block-cb-slide .gb-inside-container > a:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 18px -8px rgba(0, 33, 53, .5);
}
/* Desktop: two whole cards side by side, advancing one card at a time (the
   block's data-slick config already says slidesToShow:2 / slidesToScroll:1
   above its 769px breakpoint). wp-custom.css's `.our-services-slider
   .slick-track { margin-left: 25% }` pushed the row half a card to the
   right so only one card was ever fully in view with slivers of its
   neighbours, and its mask-image faded both edges of the list. Both are
   neutralised here at higher specificity, since wp-custom.css loads after
   this file. */
/* Title and its full stop both white (the mark carried a preset colour
   class with !important); the "Find out more" hover takes the card's own
   colour instead of the generated pink/black/blue swaps -- with a white
   ring so a card-coloured button still reads as a button on that card. */
.our-services-slider .wp-block-cb-slide > .gb-container h2,
.our-services-slider .wp-block-cb-slide > .gb-container h2 mark { color: #fff !important; }
.our-services-slider .gb-container-5aef4e79 { --card-bg: var(--wp--preset--color--green, #24D19C); }
.our-services-slider .gb-container-37204ae0 { --card-bg: var(--wp--preset--color--blue, #76C0FF); }
.our-services-slider .gb-container-07baede7 { --card-bg: #d5acf8; }
.our-services-slider .gb-container-7f9e0d80 { --card-bg: var(--wp--preset--color--primary, #f06120); }
.our-services-slider .gb-container-621458a5 { --card-bg: var(--wp--preset--color--yellow, #FFCE00); }
/* White > card-colour fill + white border/ring: the same treatment the
   Internet Connectivity page gives its white buttons (user, 2026-09-10),
   with the card colour standing in for the page accent. Transparent 2px
   border reserved at rest so hover only recolours it. */
.our-services-slider .wp-block-cb-slide > .gb-container a.gb-button {
  border: 2px solid transparent;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.our-services-slider .wp-block-cb-slide > .gb-container a.gb-button:hover,
.our-services-slider .wp-block-cb-slide > .gb-container a.gb-button:focus,
.our-services-slider .wp-block-cb-slide > .gb-container a.gb-button:active {
  background-color: var(--card-bg) !important;
  color: #fff !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px #fff !important;
}

@media (min-width: 768px) {
  .wp-block-cb-carousel.our-services-slider .slick-track { margin-left: 0; }
  .wp-block-cb-carousel.our-services-slider .slick-list { mask-image: none; -webkit-mask-image: none; }
}
@media (max-width: 767px) {
  .our-services-slider .wp-block-cb-slide.slick-slide { padding: 24px 8px; }
  .our-services-slider .wp-block-cb-slide > .gb-container { min-height: 300px; padding: 24px; }
  .our-services-slider .wp-block-cb-slide .gb-inside-container > h2 { font-size: 1.35rem; }
}

/* ================= Archiving page (content/pages/archiving.md) =================
   The page borrows Cloud Phone Systems' section containers (and its
   generated CSS via post_id 215), which style headings, paragraphs and
   buttons but have nothing for bullet lists or sub-headings -- the
   datasheet content needs both. .arch-light is for the coloured/photo
   sections, where theme.css's default dark text would vanish. */
.arch-sub { margin: 1.25em 0 .5em; font-size: 1.15rem; font-weight: 700; }
.arch-list { margin: 0 0 1.5em 1.2em; padding: 0; }
.arch-list li { margin-bottom: .55em; line-height: 1.5; }
.arch-light, .arch-light li, .arch-light strong { color: #fff; }
.arch-figure { margin: 0; }
.arch-figure img { display: block; width: 100%; height: auto; max-width: 640px; margin: 0 auto; }

/* ================= Mobile parity for service & product pages =================
   IT Essentials is the reference the user signed off: at phone width its
   text sits 10-16px in from the screen edge and is centred. Every other
   page's top-level sections (Cloud Phone Systems and the Elevate feature
   pages built on its generated CSS, the other service pages, product pages)
   had no side padding below 768px, so paragraphs, lists and headings ran to
   0-7px from the edge, and lists, sub-headings, CTA buttons, the contact
   heading and the fone-section pages (Elevate, Voice Studio, CRM, Live
   View) were left aligned. One phone-only rule set, scoped to page content
   and excluding only IT Essentials itself (leave the reference exactly as
   is; body.page-<slug> comes from base.html) and the homepage's
   Products & Services carousel cards, which are left-aligned by design.
   Blog listings and posts get the same padding and centred headings/
   cards below; article body copy stays left-aligned for readability. */
@media (max-width: 767px) {
  /* Same scheme as fonetech.uk's homepage at phone width (measured, see the
     homepage block below): the 15px gutter sits on each top-level section
     itself and the inside containers carry none -- so a section's own
     padding never stacks on top of it. Applied to every page (the user
     asked for the homepage padding on every Cloud Phone Systems page and
     the rest of the site alike). */
  body:not(.page-it-essentials) .fo-page-content > .gb-container {
    padding-left: 15px !important;
    padding-right: 15px !important;
    box-sizing: border-box;
  }
  body:not(.page-it-essentials) .fo-page-content > .gb-container > .gb-inside-container {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  body:not(.page-it-essentials) .fo-page-content .gb-inside-container:not(.our-services-slider *),
  body:not(.page-it-essentials) .fo-page-content .wp-block-column:not(.our-services-slider *),
  body:not(.page-it-essentials) .fo-page-content .fone-section,
  body:not(.page-it-essentials) .fo-page-content .fone-section-text,
  body:not(.page-it-essentials) .fo-page-content :is(h1, h2, h3, h4, p, li):not(.our-services-slider *) {
    text-align: center;
  }
  body:not(.page-it-essentials) .fo-page-content .has-text-align-left:not(.our-services-slider *) { text-align: center !important; }
  /* generated CSS gives many flex-column containers align-items:flex-start,
     which parks shrink-to-fit headings and inline-flex buttons on the left
     whatever text-align says (the homepage's Award Winning Service /
     Industries / Client Feedback blocks all did this) */
  body:not(.page-it-essentials) .fo-page-content .gb-container:not(.our-services-slider *) { align-items: center; }
  body:not(.page-it-essentials) .fo-page-content a.gb-button:not(.our-services-slider *),
  body:not(.page-it-essentials) .fo-page-content .fone-cta-btn { align-self: center; }
  /* centred text with bullet markers looks ragged: drop the markers */
  body:not(.page-it-essentials) .fo-page-content .arch-list { list-style: none; padding-left: 0; margin-left: 0; }
  body:not(.page-it-essentials) .fo-page-content figure { margin-left: auto; margin-right: auto; }
  /* Page heroes: the WiFi & Networking hero is the reference (user, 2026-09-02)
     -- its generated CSS keeps it a full viewport tall on phones, so the
     centred icon/heading/copy/button start 120px below the fixed 60px
     header. Every other hero was only 70vh, its content taller than that,
     and the overflow began at the top of the page hidden under the header
     (icons cut off, product-page headings at y=0). Same height for all,
     with header-sized padding top and bottom so centring gives exactly the
     WiFi positions, and `safe center` so content taller than the screen
     starts under the header instead of behind it. Scoped to the four
     photo-background hero containers (Cloud Phone Systems + Elevate feature
     pages, Mobile SIM / IT Essentials, WiFi / WhatsApp, Omada / Elevate) --
     the product pages' first section is only a title band, which a
     viewport-tall rule left as a lone heading in white space. */
  /* 33b466d4 (About Us + the eleven industry pages) and ec030f75 (Awards)
     added 2026-09-03 per the mobile section audit, group 1: they stopped at
     70vh (591px) and showed the next section under the fold. */
  .fo-page-content > .gb-container:first-child:is(.gb-container-1b5e3fa0, .gb-container-db878a2c, .gb-container-09b457df, .gb-container-67c9176e, .gb-container-33b466d4, .gb-container-ec030f75) {
    min-height: 100vh !important;
    padding-top: 60px !important;
    padding-bottom: 60px !important;
    box-sizing: border-box;
    display: flex;
    flex-direction: row;
    align-items: safe center;
  }
  /* product pages (Yealink / networking hardware): the title band
     sat 30px under the fixed header -- just clear it */
  .fo-page-content > .gb-container:first-child:is(.gb-container-9779332d, .gb-container-4c322818) {
    padding-top: 76px !important;
  }
  /* testimonial cards (homepage Client Feedback, WiFi page): live keeps the
     quote centred but the name/company left-aligned, with the client logo
     overlapping the card's bottom-right corner */
  body:not(.page-it-essentials) .fo-page-content .f_one_testimonial cite { display: block; text-align: left; }

  /* blog: same side padding; hero, meta, listing cards and -- on phones --
     the whole article centred (user request 2026-09-02) */
  .post-body { padding-left: 16px; padding-right: 16px; text-align: center; }
  .post-body ul, .post-body ol { list-style-position: inside; padding-left: 0; }
  .post-header, .blog-header, .pagination, .post-card-body,
  .post-body :is(h1, h2, h3, h4) { text-align: center; }
  .post-card-body { align-items: center; }

  /* desktop-only spacing that pushes text away from a neighbouring image
     (padding-right:60px on a few generated headline/paragraph and
     container rules) reads as off-centre once the columns stack */
  body:not(.page-it-essentials) .fo-page-content .gb-headline:not(.our-services-slider *) { padding-left: 0 !important; padding-right: 0 !important; }
  body:not(.page-it-essentials) .fo-page-content .gb-container-ca80ed53 { padding-right: 0 !important; }
  /* carousel slides (industries, hardware): 8px like the homepage's
     Products & Services slides, on top of the section's 15px gutter */
  body:not(.page-it-essentials) .fo-page-content .wp-block-cb-carousel:not(.our-services-slider) .wp-block-cb-slide { padding-left: 8px; padding-right: 8px; }
}

/* ================= Homepage phone layout, matched to fonetech.uk =================
   Measured on the live site at 390px (2026-09-02): every top-level section
   carries a 15px side gutter on the section itself (Award Winning Service
   20px; the hero and "People at the Heart" none) and NO side padding on its
   inside container; Products & Services and the client-logo band have no
   vertical padding of their own on phones (their inner containers carry the
   spacing). Ours had the generic 16px inside-container gutter on top of the
   sections' own padding, which pushed carousel cards and the Award copy 20-25px
   further in than live, and the logo band was 150px taller. This block comes
   after the mobile-parity rules above and wins on order at equal specificity. */
@media (max-width: 767px) {
  body.is-homepage .fo-page-content > .gb-container > .gb-inside-container { padding-left: 0 !important; padding-right: 0 !important; }
  body.is-homepage .fo-page-content > .gb-container { padding-left: 15px !important; padding-right: 15px !important; }
  body.is-homepage .fo-page-content > #header-container { padding-left: 0 !important; padding-right: 0 !important; }
  /* live: the quote text sits 13px in. The card inside scales with the
     section width, so 0 gives 8px and 5px gives 21px -- 2px lands on 13. */
  body.is-homepage .fo-page-content > #what-our-team-say { padding-left: 2px !important; padding-right: 2px !important; }
  body.is-homepage .fo-page-content > .gb-container-15dce509 { padding-left: 20px !important; padding-right: 20px !important; }
  body.is-homepage .fo-page-content > .gb-container-6af3922a { padding-top: 0 !important; padding-bottom: 0 !important; }
  /* (0,3,1) to outrank the desktop-only 100px bottom-padding fix on this band
     further down the file, which is (0,2,1) and also !important */
  body.is-homepage .fo-page-content > .gb-container-55e4be16 { padding-top: 0 !important; padding-bottom: 0 !important; }
  body.is-homepage .fo-page-content > .gb-container-5514cb03 { padding-bottom: 0 !important; }
  /* live keeps 20px on this one inside container (testimonial card gutter) */
  body.is-homepage .fo-page-content > #what-our-customers-say > .gb-inside-container { padding-left: 20px !important; padding-right: 20px !important; }
}
/* Hero: live stacks the text block and the phone-image carousel as plain
   block flow below 1025px. Ours kept the desktop flex row, so the carousel
   became a shrink-to-fit flex item -- the circular measurement Slick then
   locks in (see the .gb-grid-wrapper note near the top of this file) gave
   its track a width in the tens of millions of pixels, a 616px-tall slide
   (live: 204px) and a hero 400px taller than live with an empty band under
   the phones. Block flow gives Slick a determinate 100% width to measure. */
@media (max-width: 1024px) {
  body.is-homepage #header-container > .gb-inside-container { display: block !important; }
  body.is-homepage #header-container .gb-container-c0e5ce88,
  body.is-homepage #header-container .gb-container-c0e5ce88 .wp-block-cb-carousel { width: 100% !important; max-width: 100% !important; min-width: 0 !important; }
}

/* ================= hardware carousel columns (Cloud Phone Systems) =================
   Live's slides are a WordPress columns block with the block library's
   flex-layout gap of 2em (32px). The static export dropped the layout
   class that carries it, so on phones -- where the two columns wrap into
   text-over-image -- the "Find out more" button sat flush against the top
   of the handset photo (live: 32px between them). Same 32px sits between
   the columns side by side on desktop, as on live. */
.wp-block-cb-carousel .wp-block-columns { gap: 2em; }
/* measured on live at 390px: 53px from the button to the top of the photo */
@media (max-width: 781px) { .wp-block-cb-carousel .wp-block-columns { row-gap: 53px; } }

/* ================= latest blog post block (About Us, build-time) =================
   Markup comes from templates/partials/latest_post.html; the section's own
   generated CSS styles the h3/button, this covers the thumbnail and meta. */
.latest-post { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.latest-post-thumb { display: block; width: 100%; max-width: 460px; }
.latest-post-thumb img { display: block; width: 100%; aspect-ratio: 2.5 / 1; object-fit: cover; border-radius: 14px; }
.latest-post-meta { margin: 0; font-size: .78rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--connectivity-orange, #EE561D); }
.latest-post .gb-headline-d3943e5c { max-width: 640px; }
.latest-post h3 a { text-decoration: none; }
.latest-post h3 a:hover { text-decoration: underline; }

/* ================= "Proud to Support These Businesses" band =================
   The client-logo band carries 50px of bottom padding on its own container and
   another 50px on the section wrapping it, leaving 100px of dead space before
   the next band. Live does the same; this is a deliberate prod-only tightening.
   gb-container-55e4be16 is the shared inner container on every page that shows
   this band, so both it and its immediate section wrapper are targeted.
   !important because the per-page generated CSS sets the padding and loads
   after this file. */
.gb-container-55e4be16 { padding-bottom: 0 !important; }
.gb-container:has(> .gb-inside-container > .gb-container-55e4be16) { padding-bottom: 0 !important; }
/* On Cloud Phone Systems specifically, the :has() rule just above zeroes
   this instance's bottom padding down to 0, but the section right after
   it (Easy System Management) carries no top padding of its own -- so
   this band ends up with ~150px of breathing room above the heading and
   none at all below the logos, sitting hard against the next section.
   Restoring 150px here matches the top gap so the band reads as
   centred between the two sections either side of it. gb-container-e12aa5fe
   is this page's own unique instance id (confirmed not reused on any
   other page), so this can't affect the same band elsewhere. Specificity
   is bumped to (0,3,0) by repeating the class, since the :has() rule
   above it is already at that level and both carry !important -- source
   order alone wouldn't be enough to win the tie. */
.gb-container-e12aa5fe.gb-container-e12aa5fe.gb-container-e12aa5fe { padding-bottom: 150px !important; }
/* Same band, same problem, on the homepage -- but there it's not wrapped
   in its own outer container at all (gb-container-55e4be16 sits directly
   in .fo-page-content), so the .gb-container-55e4be16 { padding-bottom:0 }
   rule right above is the only thing zeroing it, and the fix is on that
   same element rather than an outer wrapper. Its own top gap measures
   100px, so that's what's restored. gb-container-55e4be16 is reused by
   5 other pages (about-us, f-one-technologies, and three service pages
   each with their own outer-wrapper fix above), so this is scoped to
   body.is-homepage rather than the bare class -- a small is_homepage
   flag added in _build/build.py, mirroring how page_theme_color already
   works, so it's a genuine no-op everywhere else. */
body.is-homepage .gb-container-55e4be16 { padding-bottom: 100px !important; }

/* ================= testimonial logo card =================
   theme.css positions this figure absolutely with no `top`, so it falls back to
   its static position -- which on live is after the 205px quote, putting the
   logo over the card's bottom-right corner. Here the card resolves that static
   position to the top of its content box instead, so the logo landed over the
   quote and clipped the text. Anchoring it to the bottom removes the dependency:
   a 72px overhang reproduces live on both the wifi page and the homepage. */
.f_one_testimonial figure {
  top: auto;
  bottom: -58px; /* measured on fonetech.uk at 390px, 2026-09-02 (was -72) */
  transform: none;
}
/* Phones: the client logo overlaps the review card by ~60% of its own 90px
   height (user request 2026-09-02: half, then "slightly higher still"). */
@media (max-width: 767px) {
  .f_one_testimonial figure { bottom: -35px; }
}
/* No soft drop shadow under the review card, desktop or mobile (user
   request 2026-09-02) -- theme.css draws it as the card's ::after. */
.f_one_testimonial::after { content: none !important; display: none !important; }
/* The client-logo tile keeps theme.css's soft box-shadow and has no border.
   An earlier pass (2026-09-10, "remove the blur from the review section")
   swapped the shadow for a 1px #D5E0E6 border; the user then asked for the
   border to go and the shadow to come back on the logo tile only -- the
   card's own ::after drop shadow above stays removed. */

/* ================= SITE FOOTER (matched to the live theme's real CSS) ================= */
.site-footer {
  background: linear-gradient(180deg, var(--secondary) 0%, #002135 100%);
  color: var(--text-white);
  /* No top margin -- live has none either. The last content band (the client
     logo marquee) is meant to run straight into the footer; a 60px margin left
     a strip of page background showing between them. */
  margin-top: 0;
}
/* Type sizes match live exactly: 12px/18px for both the column headings and the
   links, with no per-item margin. Prod was running 16px headings, 14px links and
   an 8px gap on every <li>, which over 54 links made the footer 777px tall
   against live's 507px. */
/* 16px of lead-in, matching live -- there the space comes from the column
   heading's own margin rather than container padding, so a 40px pad here sat
   24px too deep. */
.footer-inner { max-width: 1300px; margin: 0 auto; padding: 16px 20px 10px; }
/* 7 columns since Products was split into Phones / Networking (v24) --
   at 6 the last column ("Get in Touch") wrapped onto its own row. */
.footer-columns { display: grid; grid-template-columns: repeat(7, 1fr); gap: 24px; }
.footer-columns h4 { font-size: 12px; line-height: 18px; color: var(--text-white); margin: 0 0 16px; font-weight: 700; }
.footer-columns ul { list-style: none; margin: 0; padding: 0; }
/* line-height on the li itself, not just the link: the li inherits body's 1.5
   (24px), and that strut sets the line box floor regardless of the 18px on the
   anchor inside -- 6px per row across 19 rows is most of the extra height. */
.footer-columns li { margin-bottom: 0; line-height: 18px; }
.footer-columns a { color: var(--text-white); text-decoration: none; opacity: .85; font-size: 12px; line-height: 18px; }
.footer-columns a:hover { opacity: 1; text-decoration: underline; }
/* contact rows carry an <ion-icon> beside the link, as on live */
.footer-contact li { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 6px; }
.footer-contact ion-icon { color: var(--service-accent, var(--primary)); font-size: 15px; flex-shrink: 0; margin-top: 1px; }
.footer-contact span { min-width: 0; }
/* Live closes with one centred 12px legal line above a hairline rule */
.footer-bottom {
  max-width: 1300px;
  margin: 0 auto;
  padding: 20px;
  border-top: 1px solid rgba(255,255,255,.2);
}
.footer-bottom p {
  margin: 0;
  font-size: 12px;
  line-height: 18px;
  text-align: center;
  color: var(--text-white);
}
@media (max-width: 991px) {
  .footer-columns { grid-template-columns: 1fr 1fr; }
}
/* The group titles are <button>s (footer.html) so the phone accordion is
   accessible; on desktop they must look exactly like the plain <h4> they
   replace. theme.css styles every button orange with padding, so reset. */
.footer-col-title button {
  all: unset;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: default;
}
/* theme.css restyles button:hover/:focus/:active (grey fill, padding).
   Neutralise those properties individually -- NOT with `all: unset`: at
   (0,2,1) that outranked the phone padding rule below, so the instant a
   finger touched the row (:active/:focus) the button shrank from 44px to
   18px and the tap's click landed on the wrapper div instead. */
.footer-col-title button:hover,
.footer-col-title button:focus,
.footer-col-title button:active {
  background: none;
  color: inherit;
  border: none;
  box-shadow: none;
  outline: none;
  transform: none;
}
.footer-col-chevron { display: none; }

/* Phones: each link group collapses to a titled row with a chevron,
   separated by hairlines, as on fonetech.uk (user request 2026-09-02,
   replacing the earlier two-column packing). The Get in Touch block is not
   a group and stays open with its accent-coloured icons. */
@media (max-width: 767px) {
  .footer-columns { display: block; }
  .footer-col { border-bottom: 1px solid rgba(255, 255, 255, .14); }
  /* (0,2,0) to beat `.footer-columns h4 { margin: 0 0 16px }` above */
  .footer-columns .footer-col-title { margin: 0; }
  /* live: 12px/700 title on an 18px line with 8px above and below -- a 34px
     row pitch (ours was 61px) */
  .footer-col-title button,
  .footer-col-title button:hover,
  .footer-col-title button:focus,
  .footer-col-title button:active { padding: 8px 0; font-size: 12px; line-height: 18px; cursor: pointer; }
  .footer-col-chevron { display: block; flex-shrink: 0; transition: transform .2s ease; }
  .footer-col.is-open .footer-col-chevron { transform: rotate(180deg); }
  .footer-col > ul { display: none; padding: 0 0 8px; }
  .footer-col.is-open > ul { display: block; }
  .footer-col > ul li { line-height: 24px; }
  .footer-columns > div:not(.footer-col) { padding-top: 14px; }
}

/* ================= About Us team portraits on phones =================
   Two portraits per row instead of one 400px-tall portrait each (user
   request 2026-09-02). The name/role sit BELOW the photo in black text
   (not the desktop's white overlay on a navy gradient), in both states.
   A tap swings a tile out to full width and shows the bio under the
   name; a second tap collapses it. main.js toggles .is-expanded on the
   column below 768px; desktop keeps its hover-reveal exactly as before. */
@media (max-width: 767px) {
  /* no scroll anchoring on phones: when an open tile collapses above the
     viewport the browser would jump the page to keep some *other* element
     still (it picks anchors outside this section too), cutting into the
     glide -- so it's switched off for the whole document at this width */
  html { overflow-anchor: none; }
  #meet-the-team .gb-grid-wrapper-6ce775e9 { margin-left: -12px; row-gap: 18px; align-items: flex-start; }
  #meet-the-team .gb-grid-wrapper-6ce775e9 > .gb-grid-column {
    width: 50% !important;
    padding-left: 12px;
    /* no width transition: layout moves are animated with FLIP in main.js */
  }
  /* photo, then name/role, then (expanded only) the bio, as flex siblings:
     `display: contents` on the figure lifts the img and figcaption up next
     to the header so they can be ordered */
  #meet-the-team .team-member-container { display: flex; flex-direction: column; cursor: pointer; }
  #meet-the-team .team-member-container figure { display: contents; }
  #meet-the-team figure img {
    order: 0;
    width: 100%;
    height: auto !important;
    aspect-ratio: 5 / 6;
    object-fit: cover;
    border-radius: 16px;
  }
  #meet-the-team .team-member-header {
    display: block !important;
    order: 1;
    position: static !important;
    transform: none !important;
    width: 100% !important;
    padding: 0 2px;
    margin-top: -6px; /* tuck the name up to the photo (user, 2026-09-02) */
    background: none !important;
    color: var(--brand-body-text, #222) !important;
    text-align: center;
  }
  #meet-the-team .team-member-header::before { display: none !important; }
  /* no font-size transitions: the FLIP scale already carries the name
     visually, and a transitioning font kept changing the layout height
     above a newly opened tile for 0.5s, so its scroll target drifted */
  #meet-the-team .team-member-header h3 { font-size: 15px; line-height: 1.2; margin: 0; color: #111 !important; }
  #meet-the-team .team-member-header p { font-size: 11px; margin: 2px 0 0; color: #404040 !important; }
  /* a tap leaves the tile :hover on touch screens; don't let the desktop
     hover overlay fire on a collapsed tile */
  #meet-the-team .gb-grid-column:not(.is-bio-open):not(.is-collapsing) figure figcaption,
  #meet-the-team .gb-grid-column:not(.is-bio-open):not(.is-collapsing):hover figure figcaption,
  #meet-the-team .gb-grid-column:not(.is-bio-open):not(.is-collapsing):focus figure figcaption { display: none !important; }
  /* expanded: full width, larger name, bio beneath -- still black on white */
  /* enlarged tile is 75% of the row (user: 2026-09-02), centred via flex auto margins */
  #meet-the-team .gb-grid-wrapper-6ce775e9 > .gb-grid-column.is-expanded { width: 75% !important; margin-left: auto; margin-right: auto; }
  /* the photo eases up to size with the tile; the bio fades and rises in
     just after the tile has finished growing, instead of popping in */
  #meet-the-team .gb-grid-column.is-expanded .team-member-header h3 { font-size: 22px; }
  #meet-the-team .gb-grid-column.is-expanded .team-member-header p { font-size: 14px; }
  #meet-the-team .gb-grid-column.is-bio-open figure figcaption,
  #meet-the-team .gb-grid-column.is-collapsing figure figcaption {
    display: block !important;
    order: 2;
    /* the bio breaks out of the 75% tile to the full page width with the
       site's 15px phone gutters (user, 2026-09-02); photo and name stay
       inside the tile. The tile is centred on the page and its flex column
       centres its items, so a page-wide caption simply self-centres. */
    position: static !important;
    align-self: center;
    height: auto !important;
    width: calc(100vw - 30px) !important;
    margin-left: 0 !important;
    box-sizing: border-box;
    background: none !important;
    color: var(--brand-body-text, #404040) !important;
    padding: 10px 0 0 !important;
    border-radius: 0 !important;
    font-size: .95rem;
    line-height: 1.5;
    text-align: center;
    overflow: hidden;
    animation: team-bio-in .405s cubic-bezier(.22, .9, .3, 1) both;
  }
  /* a tile being closed (its bio still in the DOM for 450ms, see main.js)
     folds its bio away instead of dropping ~300px of height in one frame */
  #meet-the-team .gb-grid-column.is-collapsing figure figcaption {
    overflow: hidden;
    /* the fold itself is stepped by main.js (scroll-compensated) */
  }
  /* --bio-h is set by main.js to the bio's real height before each fold /
     unfold, so the visible motion spans the whole keyframe for every tile
     (a fixed 380px left short bios finished early, then a stall) */
  /* max-height runs only slightly past the bios' real height (~300px), so
     the whole duration is visible motion rather than a dead first half
     followed by a rush */
  @keyframes team-bio-in { from { opacity: 0; max-height: 0; padding-top: 0 !important; } to { opacity: 1; max-height: var(--bio-h, 380px); } }
  /* no prefers-reduced-motion override here: the team sequence animates
     regardless (user request 2026-09-03) */
}

/* ================= WhatsApp launcher on phones =================
   The msgboxx "WhatsApp / Chat with us" pill (170x60, bottom right) becomes
   just the round logo at 80% size on phones (user request 2026-09-02). Its
   own stylesheet loads after this file, hence the !importants. */
@media (max-width: 767px) {
  .msgboxxContainer .msgboxxlauncher_cta { display: none !important; }
  .msgboxxContainer .msgboxxlauncher {
    width: 48px !important;
    height: 48px !important;
    min-width: 0 !important;
    padding: 0 !important;
    background: none !important;
    box-shadow: none !important;
    border-radius: 50% !important;
  }
  .msgboxxContainer .msgboxxlauncher img {
    display: block !important;
    width: 48px !important;
    height: 48px !important;
    margin: 0 !important;
  }
}

/* ================= BLOG ================= */
/* Live renders this as a dark full-bleed hero: black behind a
   left-to-right gradient overlay, with white heading and plain white
   category links (no chips). Matched here minus the hero background
   image and search block, which the static build doesn't carry. */
/* Colours follow the homepage hero (user request 2026-09-02): navy base
   with the same dark-to-navy gradient over the photo, white heading with
   an orange full stop, white category links. The heading is NOT width-
   capped like the category row: capped at 1200px it was sitting flush
   left of the 1400px content box, so its centred text read 100px off the
   page centre on desktop. */
.blog-header {
  position: relative;
  background-color: var(--secondary);
  color: var(--text-white);
  /* leading 120px = 60px clearing the fixed header + 60px of breathing room */
  padding: 120px 20px 40px;
  text-align: center;
  z-index: 0;
}
.blog-header::after {
  content: "";
  background-image: linear-gradient(90deg, rgba(0, 33, 53, 0.62), rgba(0, 66, 105, 0.72));
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.blog-header > *:not(.post-header-background) { max-width: var(--max-width); margin-left: auto; margin-right: auto; }
.blog-header > h1 { color: var(--text-white); max-width: none !important; margin-left: 0 !important; margin-right: 0 !important; }
.blog-header h1 .dot { color: var(--connectivity-orange, #EE561D); }
.category-filter { display: flex; flex-wrap: wrap; gap: 8px 2rem; justify-content: center; margin: 20px 0 0; }
.category-filter a {
  color: var(--text-white);
  text-decoration: none;
  font-size: .85rem;
  font-weight: 600;
  opacity: .85;
}
.category-filter a.is-active, .category-filter a:hover { opacity: 1; text-decoration: underline; }

.post-grid {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 30px 20px 60px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
}
@media (max-width: 991px) { .post-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .post-grid { grid-template-columns: 1fr; } }

.post-card {
  display: flex;
  flex-direction: column;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0,0,0,.08);
  text-decoration: none;
  color: var(--brand-body-text);
  background: var(--text-white);
}
.post-card img { width: 100%; aspect-ratio: 2.5 / 1; object-fit: cover; }
.post-card-body { padding: 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
/* orange meta / navy titles -- the homepage's accent and heading colours
   (the meta was purple, the IT Essentials accent) */
.post-card-meta { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--primary); font-weight: 700; }
.post-card h3 { margin: 0; font-size: 1.05rem; color: var(--secondary); }
.post-card p { margin: 0; font-size: .9rem; opacity: .8; }
/* centred article cards on phones and tablets (user request 2026-09-02) */
@media (max-width: 991px) {
  .post-card-body { text-align: center; align-items: center; }
}

.pagination { display: flex; justify-content: center; gap: 10px; padding-bottom: 60px; }
.pagination a, .pagination span {
  padding: 8px 14px;
  border-radius: 6px;
  text-decoration: none;
  color: var(--secondary);
  background: rgba(213,172,248,.15);
  font-weight: 600;
}
.pagination .is-current { background: var(--purple); color: var(--text-white); }

/* Dark hero over the darkened featured image, matching live's
   header.blog-header treatment (black base + gradient overlay, white text). */
.post-header {
  position: relative;
  z-index: 0;
  overflow: hidden;
  background-color: var(--secondary); /* navy, as the blog index and homepage hero */
  color: var(--text-white);
  /* leading 120px = 60px clearing the fixed header + 60px of breathing room */
  padding: 120px 20px 50px;
}
.post-header::after {
  content: "";
  background-image: linear-gradient(90deg, rgba(0, 33, 53, 0.62), rgba(0, 66, 105, 0.72));
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.post-header-background {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--background, url("/assets/theme/blog-header.webp"));
  background-size: cover;
  background-position: center;
  filter: brightness(0.4);
}
.post-header > *:not(.post-header-background) { max-width: 800px; margin-left: auto; margin-right: auto; }
/* The title's auto margins were being overridden (its box sat flush left
   while the date line and back link were centred), so every post title
   read as misaligned on desktop. Force the margins and centre the header
   text (user request 2026-09-02). */
.post-header > h1 { margin-left: auto !important; margin-right: auto !important; }
.post-header { text-align: center; }
.post-header .post-card-meta { margin-bottom: 10px; }
.post-header h1 { color: var(--text-white); margin-bottom: 10px; }
.post-body { max-width: 800px; margin: 0 auto; padding: 40px 20px 60px; }
.post-body p { margin: 0 0 1.2em; }
/* live shows the featured image at the top of the content, centred and rounded */
/* Every blog photo sits in the same rounded 16:9 frame, cropped to fill it
   (user request 2026-09-02) -- a tall or square upload no longer breaks
   the shape or the corners. */
/* The blog artwork is all 2.5:1 (1500x600 / 2560x1024 "New Blog Image"
   banners), so the frame is 2.5:1 too: the full graphic shows, shrunk to the
   column, with CSS-rounded corners. The earlier 16:9 frame zoomed into the
   middle of each banner and cut its own rounded corners off, which is why
   they read as square-edged crops next to live. */
.post-featured-image { display: block; width: 100%; max-width: 760px; aspect-ratio: 2.5 / 1; object-fit: cover; margin: 0 auto 2em; border-radius: 16px; }
.back-to-blog { display: block; margin: 0 0 20px; color: var(--text-white); text-decoration: none; font-weight: 600; opacity: .85; }
.back-to-blog:hover { opacity: 1; }

/* ================= awards loop (awards-and-achievements page) =================
   Layout comes from the page's own generated CSS (generated/14674.css:
   .gb-query-523cef65 / .gb-looper-9772cf59 one-column grid, .gb-element-36666926
   200px-logo + text grid row with 150px/50px padding, the .gb-element-743e465d
   radial-gradient splitter, type sizes, and the 1024/767px breakpoints) --
   exactly as on the live site, now that the markup carries the same
   wrappers. A previous simplified flex layout here fought those rules and,
   with the wrappers missing, the awards ran side by side. Only the bits the
   generated file doesn't cover live here. */
.gb-winner { color: rgb(255, 206, 0); }
.award-loop-item:last-of-type .award-splitter { display: none; }
/* several awards share one logo: live separates them with a 100px row-gap
   between loop items; ours are consecutive label/title/text triplets in one
   column, so space each new label the same way */
.awards-wrapper .gb-text-97b128a5 + .gb-text-e2f6abdd { margin-top: 100px; }
.awards-wrapper .gb-text-97b128a5 { margin-bottom: 0; }

/* ================= GENERIC PAGE FALLBACK ================= */
.fo-page-content { margin: 0; }
.fo-page-content > .gb-block:first-child { margin-top: 0; }

/* Desktop: the "Our Team." heading sits in a flex row (theme container) and
   shrink-wraps, so its centred text still hugged the left edge; span the row */
#meet-the-team h2.wp-block-heading.has-text-align-center { width: 100%; flex: 0 0 100%; align-self: center; }

/* Phones: room below the team cards so an open bio on the last row (James
   Stacey) clears the angled divider of the next section (user, 2026-09-03) */
@media (max-width: 767px) {
  #meet-the-team { padding-bottom: 50px !important; }
}

/* ================= header sections + link cards (2026-09-03) =================
   Our Partners, About Us and Customer Area (nav.yaml `section:`) each get
   a dropdown in the Services language: a floating panel anchored under
   their own nav item holding one card shown in its expanded state.
   Everything else -- hover hold, mobile stacking, tap-to-expand -- is
   inherited from .mega-services / .mega-float-card. The link-card rules
   below only apply to header items with no children (none at present). */
/* phones only -- (0,3,3) because theme.css's `.main-navigation a { display:
   block }` outranks a lone class and showed the card next to the text link */
.main-navigation ul.menu > li > a.mega-float-card--link { display: none; }
@media (min-width: 1025px) {
  /* Panel anchored under its own nav item at the section's --mega-w (set
     inline on the li by nav.html); same chrome as the Services panel. */
  /* Centred under its own nav item (user, 2026-09-03; Services keeps its
     header-wide panel): left edge at the item's midpoint, pulled back by
     half the panel width. margin rather than transform, so the panel's
     open/close transform animation is left alone. */
  .mega-section .mega-menu--floating {
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    right: auto;
    width: var(--mega-w);
    margin-left: calc(-0.5 * var(--mega-w));
    padding: 22px; /* same as the Services panel, so the cards sit level */
  }
  /* the invisible hover bridge below the item follows the panel */
  .mega-section:hover::after,
  .mega-section.is-hover::after,
  .mega-section:focus-within::after { left: 50%; margin-left: calc(-0.5 * var(--mega-w)); }
  /* The one card sits closed, exactly like a Services card at rest, and
     swings open on hover/focus through the same .mega-float-card rules
     (user, 2026-09-03 -- an earlier cut showed it pre-expanded). Only its
     width is pinned, so it fills the panel instead of flexing. */
  .mega-section .mega-float-card,
  .mega-section .mega-float-card:hover,
  .mega-section .mega-float-card:focus-within { flex: none; width: 100%; }
  /* ten partner names read better as two columns */
  .mega-section--partners .mega-float-drop ul {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 1px 14px;
  }
}
@media (max-width: 1024px) {
  /* one 8px rhythm from the first service card to the last link card */
  .main-navigation .mega-services .mega-menu { margin: 0 0 8px; }
  .main-navigation ul.menu > li.menu-item--card { flex-direction: column; align-items: stretch; margin-bottom: 8px; }
  .main-navigation ul.menu > li.menu-item--card > a.menu-item-link { display: none; }
  /* (0,3,3) to beat both `.main-navigation ul.menu > li > a` (padding
     12px 0, width 100%) and theme.css's `.main-navigation a { display:block;
     width:max-content }` */
  .main-navigation ul.menu > li.menu-item--card > a.mega-float-card--link {
    display: block; width: 100%; height: auto; padding: 0; text-decoration: none;
  }
  /* 16px all round = what the service cards' header actually computes to
     on phones (theme.css's `.main-navigation a` padding wins there), so
     every card in the stack is the same 62px */
  .main-navigation .mega-float-card--link .mega-float-main { display: flex; width: 100%; padding: 16px; }
  .mega-float-card--link .mega-float-chevron--go { transform: none !important; }
  .mega-float-card--link:active { background: var(--text-white); border-color: rgba(0, 33, 53, .16); }
}

/* AI Call Recap / Archiving: the section they borrow from the Cloud Phone
   Systems page (67bf6e3c) is WhatsApp green there by design; on these two
   pages it is a generic requirements/add-on band and reads as off-brand, so
   it takes the page's light blue instead (user, 2026-09-03). Text stays as
   it is: dark heading + white lists, the same scheme the other blue bands
   on these pages use. */
body.page-ai-call-recap .gb-container-67bf6e3c,
body.page-archiving .gb-container-67bf6e3c { background-color: var(--blue) !important; }

/* ============ Microsoft Teams page: full Teams-purple branding ============
   (user, 2026-09-03). post_id 215 gives the page the Cloud Phone Systems
   light blue for its headings, bands and buttons; every one of those is
   restated here in Teams purple. Two tints: the brand purple for fills and
   headings on white, a lighter one for headings sitting on the dark photo
   backgrounds, where the brand purple has too little contrast. Button
   hovers already follow --service-accent (set to the same purple in
   build.py), the hero diamond is a purple recolour of the blue one. */
body.page-microsoft-teams { --teams: #5B5FC7; --teams-light: #A5A8F0; }
body.page-microsoft-teams .gb-headline-e83cf586,
body.page-microsoft-teams .gb-headline-49f83e93 { color: var(--teams-light) !important; }
body.page-microsoft-teams .gb-headline-0cab301b,
body.page-microsoft-teams .gb-headline-038bba78 { color: var(--teams) !important; }
body.page-microsoft-teams .gb-container-37fb4f12,
body.page-microsoft-teams .gb-container-b1471337 { background-color: var(--teams) !important; }
/* rest state only -- the page-scoped selector would otherwise outrank the
   shared hover rule (white fill, accent text) and leave purple on purple */
body.page-microsoft-teams a.gb-button-424478e8:not(:hover):not(:focus):not(:active),
body.page-microsoft-teams a.gb-button-a5ae33cb:not(:hover):not(:focus):not(:active),
body.page-microsoft-teams a.gb-button-009f904b:not(:hover):not(:focus):not(:active),
body.page-microsoft-teams a.gb-button-99d6ea14:not(:hover):not(:focus):not(:active),
body.page-microsoft-teams a.gb-button-13b5fd90:not(:hover):not(:focus):not(:active) { background-color: var(--teams) !important; }
/* the full stop after a purple-light heading follows the heading */
body.page-microsoft-teams[style*="--service-accent"] :is(.gb-headline-e83cf586, .gb-headline-49f83e93) mark:last-child { color: var(--teams-light) !important; }
/* The light-blue band template (37fb4f12) paints its heading and intro
   white on the Cloud Phone Systems page through that page's own section
   ids, but every other page that borrows it (Microsoft Teams, Mobile &
   Softphone Apps, ...) inherited the body grey, which reads as black on
   the colour. White everywhere the band is used (user, 2026-09-08). */
.gb-container-37fb4f12 :is(.gb-headline-85c50525, .gb-headline-a4f1c030) { color: #fff !important; }
body[style*="--service-accent"] .gb-container-37fb4f12 h2 mark:last-child { color: #fff !important; }

/* ============ WhatsApp for Business page: full WhatsApp-green branding ============
   (user, 2026-09-03). The page's own generated CSS (8749.css) is green at
   rest but hovers its buttons orange and colours its small icon links in
   the site orange; both follow the page accent (WhatsApp green) instead.
   Filled buttons hover to white with a green ring, the site's usual
   Blue > White pattern. */
body.page-whatsapp-for-business a.gb-button-d472a50b,
body.page-whatsapp-for-business a.gb-button-48f48082,
body.page-whatsapp-for-business a.gb-button-68bf05ab,
body.page-whatsapp-for-business a.gb-button-6f0676e8 {
  border: 2px solid transparent !important;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
body.page-whatsapp-for-business a.gb-button-d472a50b:hover, body.page-whatsapp-for-business a.gb-button-d472a50b:focus, body.page-whatsapp-for-business a.gb-button-d472a50b:active,
body.page-whatsapp-for-business a.gb-button-48f48082:hover, body.page-whatsapp-for-business a.gb-button-48f48082:focus, body.page-whatsapp-for-business a.gb-button-48f48082:active,
body.page-whatsapp-for-business a.gb-button-68bf05ab:hover, body.page-whatsapp-for-business a.gb-button-68bf05ab:focus, body.page-whatsapp-for-business a.gb-button-68bf05ab:active,
body.page-whatsapp-for-business a.gb-button-6f0676e8:hover, body.page-whatsapp-for-business a.gb-button-6f0676e8:focus, body.page-whatsapp-for-business a.gb-button-6f0676e8:active {
  background-color: #fff !important;
  color: var(--service-accent, #2ACC63) !important;
  border: 2px solid currentColor !important;
  box-shadow: 0 0 0 1px var(--service-accent, #2ACC63) !important;
}
body.page-whatsapp-for-business a.gb-button-75935421,
body.page-whatsapp-for-business a.gb-button-90480644,
body.page-whatsapp-for-business a.gb-button-37e5cf16,
body.page-whatsapp-for-business a.gb-button-ed164c5c,
body.page-whatsapp-for-business a.gb-button-e1829e4d { color: var(--service-accent, #2ACC63) !important; }

/* AI Call Recap / Archiving blue band: heading and intro in white, not the
   grey the borrowed section carries (user, 2026-09-03); the heading's full
   stop follows, since the page accent (light blue) would vanish on it. */
body.page-ai-call-recap .gb-container-67bf6e3c :is(.gb-headline-dc92313e, .gb-headline-af8516b7),
body.page-archiving .gb-container-67bf6e3c :is(.gb-headline-dc92313e, .gb-headline-af8516b7),
body.page-ai-call-recap[style*="--service-accent"] .gb-container-67bf6e3c h2 mark:last-child,
body.page-archiving[style*="--service-accent"] .gb-container-67bf6e3c h2 mark:last-child { color: #fff !important; }

/* Product pages' first screen (mobile section audit, group 2, option A --
   approved 2026-09-03): the title band and the product-image block below
   it share the first screen. The band is capped at 256px (76px header
   clearance + a one-line title with its padding; a two-line title's text
   still ends at 236px, only its bottom padding overflows into the empty
   top of the image block), and the image block takes the rest of the
   screen with the image centred. Pages whose image block is taller than
   that (the DECT handset galleries) simply keep their content height. */
@media (max-width: 767px) {
  .fo-page-content > .gb-container:first-child:is(.gb-container-9779332d, .gb-container-4c322818) {
    max-height: 256px;
    overflow: visible;
  }
  /* the title's 16px bottom margin otherwise escapes the band and pushes
     the image block 16px past the fold on one-line pages */
  .fo-page-content > .gb-container:first-child:is(.gb-container-9779332d, .gb-container-4c322818) :is(h1, h2) { margin-bottom: 0 !important; }
  .fo-page-content > .gb-container:first-child:is(.gb-container-9779332d, .gb-container-4c322818) + .gb-container {
    min-height: calc(100vh - 256px) !important;
    box-sizing: border-box;
    display: flex; align-items: center; justify-content: center;
  }
}

/* Elevate-family pages (Elevate, CRM Integration, Live View, Voice Studio,
   SmartVoice) -- mobile section audit, group 4 batch D, approved 2026-09-04.
   These pages' own .fone-angled dividers are SVG wedges on a transparent
   block, so the white ones vanished on the white page and every divider
   read as a 64px gap. Each wedge now overlaps the bottom of the section
   before it (blue wedge over white, white wedge over blue or over the hero
   photo) so it cuts a true angled edge, and every section fills one screen
   with its content centred and clear of the wedge. The classes exist only
   on these five pages, so no page scoping is needed. */
@media (max-width: 767px) {
  .fone-section {
    min-height: 100vh; box-sizing: border-box;
    display: flex; flex-direction: column; justify-content: center;
    padding-top: 72px !important; padding-bottom: 104px !important;
  }
  .fone-angled { margin-top: -64px; position: relative; z-index: 2; pointer-events: none; }
}

/* Mobile section audit, group 4 batches A (photo bands), B (colour bands)
   and C (white content sections) -- approved 2026-09-04. Every one of
   these section templates fills one screen on phones with its content
   centred; sections whose content already runs past a screen simply keep
   their height. First sections are excluded (the heroes have their own
   rule). The classes are the 35 templates the audit found short of a
   screen somewhere on the site. */
@media (max-width: 767px) {
  .fo-page-content > .gb-container:not(:first-child):is(.gb-container-097ee022, .gb-container-97d07ac6, .gb-container-5032885c, .gb-container-59df0676, .gb-container-99854019, .gb-container-dba2aa1b, .gb-container-b72a280d, .gb-container-9bea688f, .gb-container-b84a8afb, .gb-container-9feaae2a, .gb-container-67bf6e3c, .gb-container-37fb4f12, .gb-container-15dce509, .gb-container-264e8403, .gb-container-0e750aca, .gb-container-1203f559, .gb-container-a4508b07, .gb-container-585b1bf5, .gb-container-d8405dc1, .gb-container-48fdd6a8, .gb-container-28286b24, .gb-container-ca4f96a1, .gb-container-dbfc0811, .gb-container-b658d84e, .gb-container-d928bce5, .gb-container-3a433208, .gb-container-2082a6f7, .gb-container-7ce6aaef, .gb-container-6af3922a, .gb-container-5cb786d9, .gb-container-dd2acb76, .gb-container-4f040cac, .gb-container-d56fa762, .gb-container-920c9f46, .gb-container-a62be9a9, .gb-container-b528f460, .gb-container-1fa082cc) {
    min-height: 100vh !important; box-sizing: border-box;
    display: flex; flex-direction: column; justify-content: center;
    /* stretch, not centre: the phone parity block gives every .gb-container
       align-items:center, and on a flex COLUMN that shrink-wraps the inner
       container to its content -- a Slick carousel then sizes itself off its
       own slides and ran to 18 million px wide on the homepage (2026-09-04) */
    align-items: stretch !important;
  }
  .fo-page-content > .gb-container:not(:first-child):is(.gb-container-097ee022, .gb-container-6af3922a, .gb-container-5cb786d9, .gb-container-0e750aca, .gb-container-15dce509, .gb-container-264e8403) > .gb-inside-container { width: 100%; min-width: 0; max-width: 100%; }
  /* Batch B's angled edge: where a colour band follows a flat white section
     it gets a white wedge across its top, cut the same way as the site's
     existing dividers. The pairs below are the adjacencies the audit
     found; a wedge is never added after a photo band or an angled one. */
  .gb-container-2082a6f7 + .gb-container-9feaae2a,
  .gb-container-55e4be16 + .gb-container-0e750aca,
  .gb-container-5cb786d9 + .gb-container-264e8403,
  .gb-container-6af3922a + .gb-container-15dce509,
  .gb-container-7ce6aaef + .gb-container-48fdd6a8,
  .gb-container-9bea688f + .gb-container-1203f559,
  .gb-container-a62be9a9 + .gb-container-585b1bf5,
  .gb-container-dd2acb76 + .gb-container-a4508b07 { position: relative; padding-top: 80px !important; }
  .gb-container-2082a6f7 + .gb-container-9feaae2a::before,
  .gb-container-55e4be16 + .gb-container-0e750aca::before,
  .gb-container-5cb786d9 + .gb-container-264e8403::before,
  .gb-container-6af3922a + .gb-container-15dce509::before,
  .gb-container-7ce6aaef + .gb-container-48fdd6a8::before,
  .gb-container-9bea688f + .gb-container-1203f559::before,
  .gb-container-a62be9a9 + .gb-container-585b1bf5::before,
  .gb-container-dd2acb76 + .gb-container-a4508b07::before {
    content: ""; position: absolute; top: -1px; left: 0; right: 0; height: 48px;
    background: #fff; clip-path: polygon(0 0, 100% 0, 100% 100%); pointer-events: none;
  }
}

/* PREVIEW (audit group 5, merged) -- Mobile SIM Plans only, pending the
   user's decision (2026-09-04): Nationwide Coverage and the "Proud to
   Support These Businesses" strip become one screen. The strip keeps its
   236px and white background; Nationwide gives up that much of its screen
   so the pair ends exactly at the fold. The strip heading, which inherits
   the marquee's 1408px width and was cut off, is sized to the viewport. */
@media (max-width: 767px) {
  /* the strip already pulls 100px up into Nationwide (its own margin-top:
     -100px), so the pair is 782 + 236 - 100 = 918; trimming Nationwide's
     inner top padding (96 -> 40) and the column gap (28 -> 10) makes it
     708, and 708 + 236 - 100 = one 844px screen */
  body.page-mobile-sim-plans #nationwide { min-height: 0 !important; }
  /* keep 76px at the top so the heading clears the fixed header when the
     section is scrolled to the top; find the room in the photo instead
     (270 -> 220px tall, whole picture kept, centred) */
  body.page-mobile-sim-plans #nationwide .gb-container-0b14b100 { padding-top: 76px !important; padding-bottom: 78px !important; }
  body.page-mobile-sim-plans #nationwide .wp-block-columns { margin-bottom: 10px !important; }
  body.page-mobile-sim-plans #nationwide figure img { height: 220px !important; width: auto !important; max-width: 100%; margin: 0 auto; display: block; }
  body.page-mobile-sim-plans #clients { height: 236px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; padding: 0 !important; }
  body.page-mobile-sim-plans #clients h2 { width: 100vw; margin: 0 0 14px calc((1408px - 100vw) / 2) !important; padding: 0 15px; box-sizing: border-box; }
}

/* Thin full-screen sections (mobile section audit follow-up, user chose
   "option B" on 2026-09-04): the ten flat-background sections whose content
   is under 400px with no picture keep their full screen but the type is
   set larger (rem sizes -- em would have scaled from the 16px parent and
   made the headings smaller) so the content owns more of it. Buttons scale a little too and
   are held to one line. Voice Studio's ids also cover its SmartVoice mirror. */
@media (max-width: 767px) {
  :is(#screen-pop, #call-logging, #deployment, .gb-container-dbfc0811, #teams, #live-transcripts, #monitor-whisper-barge, #customisable, #integration, #intelligent-replies) :is(h1, h2, h3) { font-size: 2.1rem !important; line-height: 1.2 !important; } /* h1: Customer Area's View Your Bill heading */
  :is(#screen-pop, #call-logging, #deployment, .gb-container-dbfc0811, #teams, #live-transcripts, #monitor-whisper-barge, #customisable, #integration, #intelligent-replies) :is(p, li) { font-size: 1.15rem !important; line-height: 1.55 !important; }
  :is(#screen-pop, #call-logging, #deployment, .gb-container-dbfc0811, #teams, #live-transcripts, #monitor-whisper-barge, #customisable, #integration, #intelligent-replies) :is(a.gb-button, a.fone-cta-btn, .gb-button) { font-size: 1.1rem !important; padding: 0 30px !important; line-height: 24px !important; white-space: nowrap !important; }
}

/* Customer Area, Useful Information: one screen on phones (user, 2026-09-08).
   The two stacked blocks each carried 96px of padding top and bottom (384px
   of a 1118px section); trimmed to 64 / 4 / 4 / 4 (the accordion rows grew 30px when they were matched to The Basics) it comes in at 840. */
@media (max-width: 767px) {
  /* 76px on top so the heading clears the fixed header when the section is
     scrolled to the top; 8px between the two blocks; 16px at the foot */
  body.page-customerarea #brochures .gb-container-f3660215 { padding-top: 64px !important; padding-bottom: 4px !important; }
  body.page-customerarea #brochures .gb-container-29b13201 { padding-top: 4px !important; padding-bottom: 4px !important; }
}

/* Customer Area, Useful Information accordion: same formatting as The
   Basics on Cloud Phone Systems (user, 2026-09-08): bold labels, 15px 20px
   row padding, 4px between rows, content inset 20px. Each row here is
   wrapped in its own container carrying the 34px gap, so those wrappers
   are flattened with :has(). */
body.page-customerarea #brochures button.gb-accordion__toggle { padding: 15px 20px !important; font-weight: 700 !important; }
body.page-customerarea #brochures .gb-accordion-content { padding-left: 20px !important; padding-right: 20px !important; }
body.page-customerarea #brochures .gb-container:has(> .gb-inside-container > .gb-accordion-item) { padding: 0 !important; margin: 0 !important; }
body.page-customerarea #brochures .gb-container:has(> .gb-inside-container > .gb-accordion-item) > .gb-inside-container { padding: 0 !important; }
body.page-customerarea #brochures .gb-accordion-item { margin: 0 0 4px !important; }
/* the column that stacks the row wrappers is a flex column with a 30px gap */
body.page-customerarea #brochures .gb-inside-container:has(> .gb-container > .gb-inside-container > .gb-accordion-item) { gap: 0 !important; row-gap: 0 !important; }

/* Voice Studio (and its SmartVoice mirror): the hero title rendered black
   on the dark photo hero; every other hero in this family uses the page's
   light blue (user-reported 2026-09-08 via the dark-on-colour scan). */
body.page-voice-studio .fo-page-content > .gb-container:first-child h1,
body.page-smartvoice-on-hold-messaging .fo-page-content > .gb-container:first-child h1 { color: var(--blue) !important; }

/* Archiving page: sections compacted on phones (user, 2026-09-08 -- "slightly
   too long"). Inner paddings are trimmed to 64px on top (so a heading still
   clears the fixed header when its section is scrolled to the top) and 24px
   at the foot; the Search section's stacked 128/160 + 96 + 40/30 paddings
   are cut hardest; the Deployment band loses its 200/280 outer padding and
   is centred by the full-screen rule instead; lists tighten; pictures cap at
   160px. Text-heavy sections still run past a screen -- that is content,
   not spacing. */
@media (max-width: 767px) {
  body.page-archiving #what-is-archiving > .gb-inside-container { padding-top: 64px !important; padding-bottom: 24px !important; }
  body.page-archiving :is(#why-archiving .gb-container-732fed6a, #overview .gb-container-a0011b9d, #compliance-module .gb-container-925d4e10) { padding-top: 64px !important; padding-bottom: 24px !important; }
  body.page-archiving #search .gb-container-eec91306 { padding-top: 64px !important; padding-bottom: 24px !important; }
  body.page-archiving #search .gb-container-eff998ea { padding-top: 16px !important; margin-bottom: 12px !important; }
  body.page-archiving #search .gb-container-c48bf6a6 { padding-top: 16px !important; padding-bottom: 8px !important; }
  body.page-archiving #deployment { padding-top: 64px !important; padding-bottom: 40px !important; }
  body.page-archiving #deployment .gb-container-032fc88c { padding-top: 24px !important; padding-bottom: 24px !important; }
  body.page-archiving .fo-page-content li { margin-bottom: 4px !important; }
  body.page-archiving .fo-page-content ul { margin-bottom: 12px !important; }
  body.page-archiving .fo-page-content > .gb-container:not(:first-child) figure img { max-height: 160px; width: auto !important; max-width: 100%; margin: 0 auto; display: block; }
}

/* Contact form result states (Formspark background submit, main.js) */
.form-sent {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px;
  max-width: 480px; padding: 28px 24px; border-radius: 16px;
  background: var(--text-white); color: var(--secondary, #004269);
  outline: none;
}
.form-sent-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%; margin-bottom: 4px;
  background: var(--service-accent, var(--primary, #f06120)); color: #fff; font-size: 1.4rem; font-weight: 700;
}
.form-sent strong { font-size: 1.25rem; }
.form-sent span:not(.form-sent-icon) { font-size: .95rem; color: var(--text-black, #363636); opacity: .85; }
.form-error { margin-top: 10px; font-size: .9rem; font-weight: 600; color: var(--text-white); }
.wp-contact-form button[type="submit"]:disabled { opacity: .7; cursor: default; }

/* =============================================================================
   House components for hand-authored content pages  (2026-09-17)
   =============================================================================
   Elevate, CRM Integration, Live View, Voice Studio and the WiFi & Networking
   hardware grid each carry these rules in an inline <style>; those blocks
   still work and still win on those pages. They are collected here,
   parameterised on the page's accent, so a NEW page needs no inline CSS: it
   needs its slug in SERVICE_ACCENTS (build.py) and the markup documented in
   _build/README-branding.md, "Building a new content page".
   --fone-brand is the family colour: the page accent when one is set, Cloud
   Phone Systems blue otherwise, which is the value every existing page used. */
.fo-page-content { --fone-brand: var(--service-accent, var(--blue)); --fone-brand-ink: #ffffff; }
.fone-section { padding: 56px calc(max((100vw - 1100px) / 2, 1rem)); }
.fone-section.bg-tint { background: #f4f7fa; }
.fone-section.bg-brand { background: var(--fone-brand); }
.fone-section.bg-brand h2, .fone-section.bg-brand p, .fone-section.bg-brand li { color: #fff; }
.fone-section-grid { display: flex; align-items: center; gap: 48px; max-width: 1100px; margin: 0 auto; }
.fone-section-grid.reverse { flex-direction: row-reverse; }
.fone-section-text { flex: 1 1 0; min-width: 280px; }
.fone-section-text h2 { margin-top: 0; }
.fone-section-media { flex: 1 1 0; min-width: 280px; }
/* the media column holding the contact card is 544px (480px form + the
   card's 2 x 32px padding) so the form is the site-wide 480; the text
   column takes the rest. Stacked below 860px, where the card is full width. */
@media (min-width: 861px) { .fone-section-media:has(> .fone-contact-card) { flex: 0 0 544px; } }
.fone-section-media img { width: 100%; border-radius: 16px; display: block; }
.fone-section-center { max-width: 760px; margin: 0 auto; text-align: center; }
.fone-section-list { max-width: 760px; margin: 20px auto 0; text-align: left; padding-left: 1.2em; }
.fone-section-list li { margin-bottom: 8px; }
/* sub-headings and column groups inside a section (the Elevate feature
   pages, rebuilt on the house pattern 2026-09-17): an h3 over a list, and
   two to four such groups side by side under a centred heading */
.fone-section h3 { font-size: 1.15rem; font-weight: 700; margin: 1.25em 0 .5em; }
.fone-section.bg-brand h3 { color: #fff; }
.fone-section-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 8px 40px; max-width: 1100px; margin: 8px auto 0; text-align: left; }
.fone-section-cols h3 { margin-top: .75em; }
.fone-section-cols ul { margin: 0 0 1em; padding-left: 1.2em; }
.fone-section-cols li { margin-bottom: 8px; }
/* house accordion (Simon, 2026-09-18: every section that was laid out as
   columns of sub-heading + list becomes an accordion). Reuses the site's
   generic .gb-accordion markup, styling and main.js toggle; white rows on
   either a white or a coloured band, dark text inside the rows. */
.fone-accordion { max-width: 760px; margin: 24px auto 0; text-align: left; }
.fone-accordion .gb-accordion-item { background: #fff; border-radius: 12px; margin: 0 0 8px; overflow: hidden; border: 1px solid #D5E0E6; }
.fone-section.bg-brand .fone-accordion .gb-accordion-item { border-color: transparent; }
.fone-accordion .gb-accordion__toggle { padding: 14px 20px; font-weight: 700; font-size: 1.05rem; border-radius: 0; }
.fone-accordion .gb-accordion-content > div { padding: 0 20px 16px; }
.fone-accordion ul { margin: 0; padding-left: 1.2em; }
.fone-accordion li, .fone-accordion p, .fone-section.bg-brand .fone-accordion li, .fone-section.bg-brand .fone-accordion p { color: #363636; margin-bottom: 8px; }
/* the original GenerateBlocks accordion and handset carousel on the Elevate
   Phone System page: dark text inside the white accordion rows on a band,
   and the carousel's white headline and copy on the band */
.fone-section.bg-brand .gb-accordion-content :is(p, li, a:not(.gb-button)) { color: #363636; }
.fone-section .wp-block-cb-carousel { max-width: 1100px; margin: 24px auto 0; }
/* the handset carousel on the Elevate Phone System page: no arrows (the dots
   and a swipe still move it) and drawn at 90% so a slide fits one screen
   (Simon, 2026-09-18) */
body.page-cloud-phone-systems .phone-systems-carousel-new .slick-arrow { display: none !important; }
body.page-cloud-phone-systems .phone-systems-carousel-new { zoom: .9; }
/* the 90% zoom would draw the cards' "Find out more" pills at 40px; every
   button on the site is 44px (Simon, 2026-09-23), so they zoom back up */
body.page-cloud-phone-systems .phone-systems-carousel-new a.gb-button.gb-button-text { zoom: 1.1112; }
/* text links inside the house sections and accordion rows take the page
   colour rather than theme.css's site-wide orange (Simon, 2026-09-18:
   "some links are showing orange when they should match the colour theme").
   :visited is named too, as for the header number. Pills and buttons keep
   their own colours; a link sitting directly on a coloured band is white. */
body[style*="--service-accent"] :is(.fone-section, .gb-accordion-content) a:not(.fone-cta-btn):not(.gb-button):not(.fone-hw-btn),
body[style*="--service-accent"] :is(.fone-section, .gb-accordion-content) a:not(.fone-cta-btn):not(.gb-button):not(.fone-hw-btn):visited { color: var(--service-accent); }
body[style*="--service-accent"] .fone-section.bg-brand > :not(.gb-accordion) a:not(.fone-cta-btn):not(.gb-button):not(.fone-hw-btn),
body[style*="--service-accent"] .fone-section.bg-brand > :not(.gb-accordion) a:not(.fone-cta-btn):not(.gb-button):not(.fone-hw-btn):visited { color: #ffffff; }
.fone-angled { position: relative; height: 64px; overflow: hidden; line-height: 0; }
.fone-angled svg { width: 100%; height: 100%; display: block; }
.fone-cta-btn { display: inline-block; background: var(--fone-brand); color: var(--fone-brand-ink) !important; padding: 0 28px; border-radius: 999px; font-weight: 700; text-decoration: none; margin-top: 20px; }
.bg-brand .fone-cta-btn { background: #fff; color: var(--fone-brand) !important; }
.fone-contact-card { background: var(--fone-brand); border-radius: 16px; padding: 32px; }
.fone-contact-card h2, .fone-contact-card p, .fone-contact-card label { color: #fff !important; }
/* an icon or logo on a tile in a media slot (CRM Integration's pattern):
   tinted on a white section, white on a coloured one */
.fone-tile { display: block; max-width: 420px; margin: 0 auto; background: #f4f7fa; padding: 24px; border-radius: 16px; }
.bg-brand .fone-tile { background: #fff; }
/* card grid (WiFi & Networking's hardware cards) */
.fone-hw { padding: 72px calc(max((100vw - 1100px) / 2, 1rem)); background: #f4f7fa; }
.fone-hw h2 { text-align: center; margin: 0 0 12px; }
.fone-hw > p { text-align: center; max-width: 720px; margin: 0 auto 36px; }
.fone-hw-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; max-width: 1100px; margin: 0 auto; }
.fone-hw-card { background: #fff; border-radius: 16px; padding: 24px 20px 28px; text-align: center; box-shadow: 0 12px 28px -18px rgba(0, 33, 53, .3); display: flex; flex-direction: column; align-items: center; }
.fone-hw-card img { width: 100%; height: 170px; object-fit: contain; margin-bottom: 16px; }
.fone-hw-card h3 { margin: 0 0 8px; font-size: 1.15rem; }
.fone-hw-card p { margin: 0 0 18px; font-size: .95rem; line-height: 1.5; flex: 1; }
.fone-hw-btn { display: inline-block; background: var(--fone-brand); color: var(--fone-brand-ink) !important; padding: 0 28px; border-radius: 999px; font-weight: 700; text-decoration: none; }
/* a logo card. The Knowledge Base logos are square canvases with the mark
   in the middle third, so they need the full photo height to read */
.fone-hw-card--logo img { height: 170px; }
@media (max-width: 991px) { .fone-hw-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 860px) { .fone-section-grid, .fone-section-grid.reverse { flex-direction: column; } }
@media (max-width: 560px) { .fone-hw-grid { grid-template-columns: 1fr; } }
/* heading colour for a page whose family colour is its own accent (partner
   pages): does the job has-blue-color etc. do in brand.css, for colours with
   no WordPress preset class */
.has-accent-color { color: var(--service-accent, var(--secondary)) !important; }
/* partner pages borrow a family's hero (generated_css in the front matter);
   the gradient's right-hand end is the family colour in that CSS, so it is
   swapped for the partner colour here */
body[class*="page-partners"] .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.63) 20%, var(--service-accent, var(--blue))); }
/* on a partner hero the headline is white and its dot follows the neighbouring
   text (the Knowledge Base's rule for headings on dark or coloured grounds):
   a dark partner colour such as Intermedia's would otherwise vanish there.
   Outranks the site-wide accent-dot rule on specificity. */
body[class*="page-partners"] .gb-container-67c9176e h1 mark:last-child,
body.page-microsoft-teams .gb-container-67c9176e h1 mark:last-child { color: #ffffff !important; }   /* Teams: its purple dot is too dim on the dark hero */
/* hover for the house pills (2026-09-17, user: "the hover function is broken").
   The inline <style> blocks on Elevate and its siblings never gave
   .fone-cta-btn a hover state, so these pills sat dead while the header and
   hero buttons flipped. Same system as those buttons: filled > white with the
   accent as text, a 2px border and a 1px ring; on a coloured band the white
   pill fills with the accent under a white border and ring. The border is an
   inset shadow, not a real border, so the pill never changes size. */
.fone-cta-btn, .fone-hw-btn { transition: background-color .18s ease, color .18s ease, box-shadow .18s ease; }
.fone-cta-btn:hover, .fone-cta-btn:focus, .fone-hw-btn:hover, .fone-hw-btn:focus {
  background: #fff;
  color: var(--fone-brand) !important;
  box-shadow: inset 0 0 0 2px var(--fone-brand), 0 0 0 1px var(--fone-brand);
}
.bg-brand .fone-cta-btn:hover, .bg-brand .fone-cta-btn:focus {
  background: var(--fone-brand);
  color: #fff !important;
  box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #fff;
}
/* Headings on a band of the accent colour keep a visible dot (user,
   2026-09-17: "on the coloured banners the headings are missing their '.'").
   The site-wide accent-dot rule above colours every heading's last <mark>
   with the page accent; on a .bg-brand section or the contact card the
   background IS the accent, so the dot disappeared -- on Elevate, CRM
   Integration, Live View and Voice Studio as well as the partner pages.
   White here, following the Knowledge Base rule that a dot on a coloured
   ground takes its neighbour's colour. Outranks the accent rule. */
body[style*="--service-accent"] :is(.fone-section.bg-brand, .fone-contact-card) :is(h1, h2, h3, h4) mark:last-child { color: #ffffff !important; }
/* Divider shapes for hand-authored pages (2026-09-17, user: "more variety in
   angled elements, but consistent across the pages"). The four shapes are
   the site's own GenerateBlocks dividers (gbrender.py SHAPE_SVGS), redrawn
   as .fone-angled variants so a hand-authored page can use the same set the
   service pages do. Each variant is a band of the NEXT section's colour
   with a shaped top edge; a shape that lets the PREVIOUS section's colour
   reach down (a point or a diagonal cut into a coloured band) puts that
   colour on the divider's background, which is what keeps the shape correct
   on phones, where every divider overlaps the section before it by its own
   height. The height lives in --fone-angled-h so that overlap follows it. */
.fone-angled { --fone-angled-h: 64px; }
.fone-angled--angle { height: 100px; --fone-angled-h: 100px; }   /* gb-angle-1 */
.fone-angled--point { height: 100px; --fone-angled-h: 100px; }   /* gb-triangle-1: point down */
.fone-angled--peak  { height: 120px; --fone-angled-h: 120px; }   /* gb-triangle-8: centred peak */
@media (max-width: 767px) {
  .fone-angled { margin-top: calc(-1 * var(--fone-angled-h)); }
  .fone-angled--peak { height: 100px; --fone-angled-h: 100px; }  /* section padding clears 104px */
}

/* Industries pages -- divider parity with Care Homes (2026-09-17, user:
   "apply the same consistency" to the Industries pages). All eleven share one
   template (33b466d4 hero > 9bea688f testimonial > 5032885c photo band >
   b84a8afb colour band > 097ee022 photo band > d928bce5 contact > ticker),
   but only Care Homes' export carried the photo band's bottom shape and the
   fifth section's top triangle; the other ten had one divider each. Their
   markup now matches Care Homes (gbrender-style .gb-shapes, added in the
   content), and these rules supply what their generated CSS lacks: the
   bottom angle on 5032885c in the colour of the band that follows it, the
   top triangle on 097ee022 in the same colour, and the existing top angle
   at Care Homes' 200px. Colours come from each page's own b84a8afb band. */
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-5032885c > .gb-shapes .gb-shape-1 svg { height: 200px; }
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-5032885c > .gb-shapes .gb-shape-2 {
  z-index: 5; position: absolute; overflow: hidden; pointer-events: none; line-height: 0;
  left: 0; right: 0; bottom: -1px; transform: scaleX(-1);
}
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-5032885c > .gb-shapes .gb-shape-2 svg,
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-097ee022 > .gb-shapes .gb-shape-1 svg {
  width: calc(100% + 1.3px); fill: currentColor; position: relative; left: 50%; transform: translateX(-50%); min-width: 100%;
}
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-5032885c > .gb-shapes .gb-shape-2 svg { height: 150px; }
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-097ee022 > .gb-shapes .gb-shape-1 {
  z-index: 2; position: absolute; overflow: hidden; pointer-events: none; line-height: 0;
  left: 0; right: 0; top: -1px; transform: scaleY(-1) scaleX(-1);
}
body:is(.page-dental-practices, .page-doctors-surgeries, .page-golf-clubs, .page-veterinary-practices, .page-education-solutions, .page-general-office, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) .gb-container-097ee022 > .gb-shapes .gb-shape-1 svg { height: 100px; }
/* the colour of the band that follows the photo band, per page */
body:is(.page-dental-practices, .page-doctors-surgeries, .page-education-solutions, .page-warehouses, .page-estate-agencies, .page-recruitment-agencies, .page-serviced-offices) :is(.gb-container-5032885c > .gb-shapes .gb-shape-2, .gb-container-097ee022 > .gb-shapes .gb-shape-1) { color: var(--wp--preset--color--blue, #76C0FF); }
body.page-golf-clubs :is(.gb-container-5032885c > .gb-shapes .gb-shape-2, .gb-container-097ee022 > .gb-shapes .gb-shape-1) { color: var(--wp--preset--color--yellow, #FFCE00); }
body.page-veterinary-practices :is(.gb-container-5032885c > .gb-shapes .gb-shape-2, .gb-container-097ee022 > .gb-shapes .gb-shape-1) { color: var(--wp--preset--color--pink, #CC289C); }
body.page-general-office :is(.gb-container-5032885c > .gb-shapes .gb-shape-2, .gb-container-097ee022 > .gb-shapes .gb-shape-1) { color: var(--wp--preset--color--secondary, #004269); }

/* Intermedia hero (2026-09-17, user: "make the Intermedia hero look like
   this... mainly the colouring and spiral shape"): the borrowed photo hero
   keeps its layout, type, icon and button; only the ground changes.
   Intermedia's blue-to-turquoise sweep replaces the photo and the dark wash,
   with a drawn ribbon of thin white lines over it
   (assets/uploads/partners/intermedia-hero-waves.svg, drawn by
   _build/hero_waves.py -- our own drawing; Simon, 2026-09-18: no
   copyrighted material, so Intermedia's own ribbon artwork is not used). A faint darker pool sits behind the
   copy so the white text still reads where the turquoise runs light. */
body.page-partners-intermedia .gb-container-67c9176e { background-color: #1e5cf6; background-image: linear-gradient(100deg, #1e5cf6 0%, #1b9df3 50%, #0ce0cd 100%); }
body.page-partners-intermedia .gb-container-67c9176e:before { background-image: url(/assets/uploads/partners/intermedia-hero-waves.svg); background-position: left center; background-size: cover; opacity: 1; }   /* anchored left so the band's pinch stays in view on narrower screens */
body.page-partners-intermedia .gb-container-67c9176e:after { background-image: radial-gradient(ellipse 55% 60% at 50% 55%, rgba(0, 40, 120, 0.28), rgba(0, 40, 120, 0) 100%); }



/* Elevate Key Features and Integrations pages -- each borrows the Cloud
   Phone Systems hero block but carries its own photo (Simon, 2026-09-17: the
   pages "look too similar"). Photos are the site's own full-width set and the
   Knowledge Base's generated Website Imagery, saved as JPEGs in uploads/hero/. */
body.page-mobile-and-softphone-apps .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/site-manager-on-mobile.jpg); }
body.page-call-queues-and-hunt-groups .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/receptionist-on-desk-phone.jpg); }
body.page-whatsapp-for-business .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-2-5-scaled.png); }
body.page-ai-call-recap .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-8-2-scaled.png); }
body.page-sentiment-and-topic-analysis .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-4-4-scaled.png); }
body.page-live-view .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/desk-with-yealink-and-elevate-app.jpg); }
body.page-archiving .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-5-3-scaled.png); }
body.page-microsoft-teams .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-6-4-scaled.png); }
body.page-crm-integration .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/business-review-meeting.jpg); }
body.page-voice-studio .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-8-4-scaled.png); }
body.page-elevate .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-16-1-scaled.png); }
body.page-cloud-phone-systems .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-22-1-scaled.png); }
/* WhatsApp and Teams are branded after the product, so their hero gradient
   ends in the product colour, as the partner heroes do */
body:is(.page-whatsapp-for-business, .page-microsoft-teams) .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.63) 20%, var(--service-accent)); }
/* WhatsApp and Teams are branded after the product, so their hero gradient
   ends in the product colour, as the partner heroes do */
body:is(.page-whatsapp-for-business, .page-microsoft-teams) .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.63) 20%, var(--service-accent)); }
/* WhatsApp and Teams are branded after the product, so their hero gradient
   ends in the product colour, as the partner heroes do */
body:is(.page-whatsapp-for-business, .page-microsoft-teams) .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.63) 20%, var(--service-accent)); }

/* Our Partners index hero: a ground drawn from the ten partner circles,
   tiled at an angle (Simon, 2026-09-18: "the hero banner picture should
   include all of the logos"), made by _build/partner_grounds.py. */
body.page-partners .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/our-partners.svg); background-position: center; opacity: .9; }
body.page-partners .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.55) 15%, var(--service-accent)); opacity: .85; }

/* Partner heroes (Simon, 2026-09-18: "do not use any copyrighted material").
   Only F One's own pictures or the site's existing photos: TP-Link and Social
   WiFi take the Knowledge Base's generated Website Imagery, Yealink a site
   photo with a Yealink handset on the desk. Every other partner page keeps
   the family hero. Nothing here is taken from a partner's website. */
body.page-partners-tp-link .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/tp-link-engineer.jpg); }
body.page-partners-social-wifi .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/guest-on-phone-in-cafe.jpg); }
body.page-partners-yealink .gb-container-67c9176e:before { background-image: url(/assets/uploads/Full-Width-Page-Image-Website-21-1-scaled.png); }
/* Drawn grounds (Simon, 2026-09-18: "generate AI versions that look similar
   and use these instead"): original abstract SVGs in each partner's colours,
   made by _build/partner_grounds.py, nothing copied. They run brighter than
   a photo so they read as a ground rather than a dim wash; the dark sweep
   above still carries the copy. */
body.page-partners-red-cactus .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/red-cactus.svg); opacity: .95; }
body.page-partners-ninjaone .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/ninjaone.svg); opacity: .95; }
body.page-partners-acronis .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/acronis.svg); opacity: .95; }
body.page-partners-microsoft .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/microsoft.svg); opacity: .8; }
body.page-partners-worldpay .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/worldpay.svg); opacity: .9; }
body.page-partners-hikvision .gb-container-67c9176e:before { background-image: url(/assets/uploads/hero/grounds/hikvision.svg); opacity: .95; }
/* a lighter wash over a drawn ground than over a photo, so the drawing shows */
body:is(.page-partners-red-cactus, .page-partners-ninjaone, .page-partners-acronis, .page-partners-microsoft, .page-partners-worldpay, .page-partners-hikvision) .gb-container-67c9176e:after { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.45) 15%, var(--service-accent)); opacity: .85; }

/* Homepage hero: the banner slider sits 90px higher (Simon, 2026-09-24:
   "the carousel on the homepage is cutting off some of the pictures, shift
   the images all up slightly"). Nothing clips the pictures; on a laptop
   screen they simply started 443px down, so the bottom of a 600px banner
   (the monitors' keyboard, the phones' bases) fell 180-335px below the
   first screen. The lift comes from the hero's own spacing in the
   generated CSS: 150px above the headline becomes 120, and the 30px + 30px
   between the "Get in touch" button and the slider goes, the banners
   themselves carrying about 60px of plain blue above their subject. Tablet
   and desktop only: below 768px the export lays the hero out with its own
   negative margins, left alone. */
@media (min-width: 768px) {
  body.is-homepage .gb-container-cb10e192 { padding-top: 120px; padding-bottom: 0; }
  body.is-homepage .gb-container-c0e5ce88 { padding-top: 0; }
}

/* Cloudflare Turnstile widget in every form (build.py add_turnstile) */
.cf-turnstile { margin: 14px 0 4px; }
/* Contact page, Request a Quote: the navy panel hugs its fields instead of
   running the full 60% column with a wide empty band to the right of them
   (Simon, 2026-09-24: "this doesn't need to be as wide" / "shrink the
   request a quote field to match the field widths"). The panel's inner
   container is a flex row aligned to the start, so the form already
   shrinks to the select's own width; the panel now takes that content
   width plus its 2em padding, capped at the column on phones. The Message
   the Team panel already sits tight round its 480px form. */
/* ...and pushed to the right edge of its column (margin-left: auto), which
   is the same right edge the Message the Team panel above sits on, so the
   two line up (Simon, 2026-09-24: "shove the quote tool to the right to
   align with the form above it, keep the current width"). */
body.page-contact-us .gb-container-706d6a17 { width: fit-content; max-width: 100%; margin-left: auto; }
.fone-contact-card .cf-turnstile { margin-bottom: 8px; }
