@charset "UTF-8";
/* ==========================================================================
   Regan IT — site stylesheet
   --------------------------------------------------------------------------
   Single source of truth for the custom layer. Sits on top of Bootstrap 4
   (grid + navbar collapse only) and FontAwesome (top-bar icons). It replaces
   the old template style.css / responsive.css, which mixed six unrelated
   card treatments and loaded its webfonts through an @import placed AFTER a
   rule — invalid, so Lato and Merriweather Sans never actually loaded and
   every page fell back to system sans.

   Everything is built from one card component (.ri-card) and one section
   rhythm (.ri-section + .ri-head), which is what makes the pages match.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */

:root {
  /* Deepwater palette: analogous blue family, one complementary coral.
     Contrast against #fff — navy 18.1:1, primary 7.2:1, accent 5.2:1. */
  --ink:            #12293D;
  --ink-soft:       #2C3E4C;
  --primary:        #1F5C82;
  --primary-light:  #4E86A8;
  --wash:           #E7EFF4;
  --wash-deep:      #D6E4EC;
  --accent:         #B84A32;
  --accent-light:   #D9694F;
  --muted:          #5C6B75;
  --surface:        #FFFFFF;

  /* Neutrals carry a blue bias so they read as chosen, not defaulted. */
  --line:           #D3E0E8;
  --line-soft:      #E4EDF2;

  /* On the navy band. */
  --on-dark:        #FFFFFF;
  --on-dark-soft:   #AFC6D5;
  --on-dark-line:   rgba(175, 198, 213, 0.26);
  --on-dark-fill:   rgba(255, 255, 255, 0.055);

  /* The serif echoes the wordmark in the logo; the grotesque does the work. */
  --font-display: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --font-body:    'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  --shadow-sm: 0 1px 3px rgba(18, 41, 61, 0.07), 0 4px 14px rgba(18, 41, 61, 0.06);
  --shadow-md: 0 4px 10px rgba(18, 41, 61, 0.08), 0 14px 34px rgba(18, 41, 61, 0.10);
  --shadow-lg: 0 10px 24px rgba(18, 41, 61, 0.13), 0 26px 60px rgba(18, 41, 61, 0.14);

  --radius:    14px;
  --radius-sm: 9px;
  --gutter:    28px;
}

/* ---------- 2. Base ----------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink-soft);
  background-color: var(--surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img { max-width: 100%; height: auto; border: 0; }

a { color: var(--primary); text-decoration: none; transition: color .2s ease; }
a:hover, a:focus { color: var(--accent); text-decoration: none; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

ul { margin: 0; padding: 0; list-style: none; }

/* ---------- 3. Typography ---------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.6em;
  line-height: 1.15;
  text-wrap: balance;
  letter-spacing: -0.012em;
}

h1 { font-size: clamp(2.1rem, 1.35rem + 2.6vw, 3.35rem); }
h2 { font-size: clamp(1.75rem, 1.25rem + 1.7vw, 2.5rem); }
h3 { font-size: 1.2rem; line-height: 1.3; letter-spacing: -0.006em; }
h4 { font-size: 1.05rem; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.ri-lede {
  font-size: clamp(1.06rem, 1rem + 0.3vw, 1.22rem);
  line-height: 1.6;
  color: var(--ink-soft);
}

/* Uppercase, letter-spaced category label. Used above every section heading
   and at the top of every card, so a card and a section read as the same
   family of object. */
.ri-eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: 0.735rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 0.85em;
}

.ri-measure { max-width: 64ch; }

/* ---------- 4. Sections ------------------------------------------------- */

.ri-section { padding: clamp(64px, 4vw + 40px, 108px) 0; }
.ri-section--tight { padding: clamp(48px, 3vw + 30px, 76px) 0; }
.ri-section--wash { background-color: var(--wash); }
.ri-section--dark { background-color: var(--ink); }

.ri-head {
  max-width: 62ch;
  margin: 0 auto clamp(38px, 3vw, 56px);
  text-align: center;
}

.ri-head--left { margin-left: 0; text-align: left; }
.ri-head p { color: var(--muted); }
.ri-head h2 { margin-bottom: 0.45em; }

.ri-section--dark .ri-head h2,
.ri-section--dark h2,
.ri-section--dark h3 { color: var(--on-dark); }
.ri-section--dark .ri-head p { color: var(--on-dark-soft); }
.ri-section--dark .ri-eyebrow { color: var(--primary-light); }

/* ---------- 5. Buttons ------------------------------------------------- */

.ri-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 13px 30px;
  border-radius: 7px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: background-color .22s ease, color .22s ease, border-color .22s ease, transform .22s ease;
}

.ri-btn:hover, .ri-btn:focus { transform: translateY(-2px); }

.ri-btn--primary {
  background-color: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.ri-btn--primary:hover, .ri-btn--primary:focus {
  background-color: #9E3D28;
  border-color: #9E3D28;
  color: #fff;
}

.ri-btn--ghost {
  background-color: transparent;
  border-color: var(--primary);
  color: var(--primary);
}
.ri-btn--ghost:hover, .ri-btn--ghost:focus {
  background-color: var(--primary);
  color: #fff;
}

.ri-btn--on-dark {
  background-color: transparent;
  border-color: var(--on-dark-soft);
  color: var(--on-dark);
}
.ri-btn--on-dark:hover, .ri-btn--on-dark:focus {
  background-color: var(--on-dark);
  border-color: var(--on-dark);
  color: var(--ink);
}

.ri-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 8px;
}

/* Text link with a chevron, for use at the foot of a card. */
.ri-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--primary);
  margin-top: auto;
  padding-top: 18px;
}
.ri-link::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 2px solid currentColor;
  border-top: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform .2s ease;
}
.ri-link:hover::after { transform: rotate(45deg) translate(2px, -2px); }

/* ---------- 6. The card ------------------------------------------------
   One component, used for services, credentials, the feature trio, the
   reasons-to-choose grid and the contact methods. Every grid on the site is
   .ri-grid > .ri-card, which is what stops the pages drifting apart.       */

.ri-grid {
  display: grid;
  gap: var(--gutter);
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

.ri-grid--2 { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.ri-grid--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* Four cards, always balanced. auto-fit steps 4 -> 3 -> 2 as the viewport narrows,
   and the 3 state orphans the fourth card on a row of its own, which is what both
   pricing grids were doing at desktop width. Explicit columns instead: 2x2 down to
   620px, then stacked. Cards land ~552px wide at max container, so the prices have
   room rather than being squeezed four across. */
.ri-grid--quad { grid-template-columns: repeat(2, 1fr); }

/* Price ladders. Four ascending tiers have to read left to right as steps up, so
   2x2 is wrong here even though it balances - it splits the ladder into two
   unrelated pairs. Four across it is, and the price drops from 2.15rem to 1.85rem
   at that width so "from £1,495" fits the ~206px of text a 262px card leaves after
   padding. Below 1100px there is no longer room for four, so it becomes 2x2, then
   stacks. Never three-and-an-orphan, which is what auto-fit was doing. */
/* Twelve service cards in a 3-col grid is four rows and a long scroll. Four across
   makes three rows. The cards get narrower so the body copy is stepped down a notch to
   stop it becoming a column of two-word lines. 12 divides by 4, 2 and 1, so no
   arrangement orphans a card. Explicit columns rather than auto-fit, same as the
   tiers grid, so it cannot land on a 3-wide state at some in-between width. */
/* Type scale only. Composes with whatever column class it is paired with, so the
   card count decides the columns and this just tightens the contents. */
.ri-grid--compact .ri-card { padding: 24px 22px 22px; }
.ri-grid--compact .ri-card h3 { font-size: 1.04rem; line-height: 1.25; }
.ri-grid--compact .ri-card p { font-size: 0.875rem; line-height: 1.5; }
.ri-grid--compact .ri-ico { width: 40px; height: 40px; margin-bottom: 12px; }
.ri-grid--compact .ri-ico svg { width: 21px; height: 21px; }

.ri-grid--tiers { grid-template-columns: repeat(4, 1fr); }
.ri-grid--tiers .ri-pack__price { font-size: 1.85rem; }
.ri-grid--tiers .ri-pack li { font-size: 0.9rem; }
@media (max-width: 1100px) {
  .ri-grid--tiers { grid-template-columns: repeat(2, 1fr); }
  .ri-grid--tiers .ri-pack__price { font-size: 2.15rem; }
}
@media (max-width: 620px) { .ri-grid--tiers { grid-template-columns: 1fr; } }
@media (max-width: 620px) { .ri-grid--quad { grid-template-columns: 1fr; } }
.ri-grid--4 { grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); }

/* Four pricing tiers. Deliberately NOT ri-grid--4: at ~1024px the 28px gutters
   leave 223px per column against that grid's 232px minimum, so it collapses to
   three and orphans the fourth card on a row of its own. A four-across column is
   too narrow for the price anyway — "from £1,495" runs to about 253px at its
   display size and would clip. A 320px minimum gives 1 / 2x2 / 4 instead. */
.ri-grid--packs { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.ri-card {
  display: flex;
  flex-direction: column;
  background-color: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 30px 26px 28px;
  box-shadow: var(--shadow-sm);
  transition: transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}

.ri-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--primary-light);
}

.ri-card h3 { margin-bottom: 0.5em; }
.ri-card p { color: var(--muted); font-size: 0.965rem; }

/* Dark variant, for the navy credentials band. */
.ri-card--dark {
  background-color: var(--on-dark-fill);
  border-color: var(--on-dark-line);
  box-shadow: none;
}
.ri-card--dark h3 { color: var(--on-dark); }
.ri-card--dark p { color: var(--on-dark-soft); }
.ri-card--dark .ri-eyebrow { color: var(--primary-light); }
.ri-card--dark:hover {
  background-color: rgba(255, 255, 255, 0.085);
  border-color: var(--accent-light);
  box-shadow: none;
}

/* Wash variant, for a card sitting on the pale ground. */
.ri-card--plain { box-shadow: none; border-color: var(--line); }
.ri-card--plain:hover { box-shadow: var(--shadow-sm); }

/* ---------- 7. Card icon ----------------------------------------------
   Stroked 24×24 glyphs, one weight, one corner treatment. Replaces the six
   mismatched raster icons the template shipped (three of which were 250–410KB
   photographic PNGs). .ri-ico-mark is the stroke that gets the coral accent. */

.ri-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  margin-bottom: 22px;
  border-radius: 12px;
  background-color: var(--wash);
  color: var(--primary);
  flex: 0 0 auto;
}

.ri-ico svg { width: 29px; height: 29px; display: block; }

.ri-ico svg path,
.ri-ico svg circle,
.ri-ico svg rect,
.ri-ico svg line,
.ri-ico svg polyline {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ri-ico svg .ri-ico-mark { stroke: var(--accent); stroke-width: 1.9; }
.ri-ico svg .ri-ico-dot   { fill: currentColor; stroke: none; }

.ri-card--dark .ri-ico {
  background-color: rgba(255, 255, 255, 0.075);
  color: var(--primary-light);
}
.ri-card--dark .ri-ico svg .ri-ico-mark { stroke: var(--accent-light); }

/* ---------- 8. Top bar + nav ------------------------------------------- */

.ri-topbar {
  background-color: var(--ink);
  color: var(--on-dark-soft);
  font-size: 0.875rem;
}

.ri-topbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 30px;
  padding: 9px 0;
}

.ri-topbar a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--on-dark-soft);
  font-weight: 500;
}
.ri-topbar a:hover { color: #fff; }
.ri-topbar .fa { color: var(--accent-light); font-size: 0.95em; }

.ri-header {
  position: sticky;
  top: 0;
  z-index: 900;
  background-color: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
          backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid var(--line-soft);
}

.ri-header .navbar { padding: 14px 0; }

.ri-header .navbar-brand { padding: 0; margin: 0; }
.ri-header .navbar-brand img {
  width: 252px;
  height: auto;
  display: block;
}

.ri-header .navbar-nav { gap: 4px; }

.ri-header .nav-link {
  position: relative;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink);
  padding: 8px 15px;
  border-radius: 6px;
}

.ri-header .nav-link:hover { color: var(--primary); background-color: var(--wash); }

.ri-header .nav-item.active > .nav-link { color: var(--primary); font-weight: 600; }
.ri-header .nav-item.active > .nav-link::after {
  content: "";
  position: absolute;
  left: 15px; right: 15px; bottom: 2px;
  height: 2px;
  background-color: var(--accent);
  border-radius: 2px;
}

.ri-header .ri-nav-cta { margin-left: 12px; }

/* Web Design submenu. CSS only, deliberately: hover plus :focus-within covers
   mouse and keyboard, and inside the collapsed mobile menu it becomes a plain
   indented list that is always open. That avoids the tap-to-open versus
   tap-to-navigate problem on touch screens, and keeps the parent a real link. */
.ri-header .ri-has-drop { position: relative; }

.ri-header .ri-drop {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 60;
  min-width: 236px;
  margin: 0;
  padding: 6px;
  list-style: none;
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s ease;
}

.ri-header .ri-has-drop:hover > .ri-drop,
.ri-header .ri-has-drop:focus-within > .ri-drop {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.ri-header .ri-drop a {
  display: block;
  padding: 9px 12px;
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}

.ri-header .ri-drop a:hover,
.ri-header .ri-drop a:focus-visible { color: var(--primary); background-color: var(--wash); }

.ri-header .ri-drop [aria-current="page"] { color: var(--primary); font-weight: 600; }

.ri-header .ri-drop-arrow {
  width: 11px;
  height: 11px;
  margin-left: 4px;
  vertical-align: -1px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.16s ease;
}

.ri-header .ri-has-drop:hover .ri-drop-arrow,
.ri-header .ri-has-drop:focus-within .ri-drop-arrow { transform: rotate(180deg); }

/* Seven items plus the call button is tight where the horizontal nav first
   appears, so buy back a little room rather than let the row wrap. */
/* Between 992 and 1199 the header has to fit brand + six links + the call button
   inside 976px of usable width. Renaming "Web Design" to "Websites and SEO" added
   ~53px and pushed it onto a second row (header 84px -> 139px). Trimming the link
   padding and the wordmark buys ~73px back, which restores one row with headroom.
   Measured 2026-09-08 with SEVEN top-level items (Tools added): one row, 24px slack.
   That is the ceiling. An EIGHTH does not fit. Measure with getBoundingClientRect. */
@media (min-width: 992px) and (max-width: 1199px) {
  .ri-header .nav-link { padding-left: 8px; padding-right: 8px; }
  .ri-header .nav-item.active > .nav-link::after { left: 8px; right: 8px; }
  .ri-header .navbar-brand img { width: 212px; }
  .ri-header .navbar-nav { gap: 2px; }
}

.ri-header .navbar-toggler {
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 9px 11px;
  background: none;
  cursor: pointer;
}
.ri-header .navbar-toggler-bar {
  display: block;
  width: 21px;
  height: 2px;
  background-color: var(--ink);
  border-radius: 2px;
}
.ri-header .navbar-toggler-bar + .navbar-toggler-bar { margin-top: 5px; }

/* ---------- 9. Hero ---------------------------------------------------- */

.ri-hero {
  background-color: var(--wash);
  /* Bottom padding was oversized to make room for .ri-hero-cards overlapping
     upward into it. Those teaser cards were removed on 2026-09-02 (they
     duplicated the Services grid and all three linked to the same page), so the
     hero now closes at the same rhythm as every other section. */
  padding: clamp(52px, 4vw + 26px, 96px) 0 clamp(56px, 4vw + 20px, 88px);
  overflow: hidden;
}

.ri-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(34px, 4vw, 68px);
  align-items: center;
}

.ri-hero h1 { margin-bottom: 0.5em; max-width: 22ch; }
/* Service pages run a text-only hero: no stock photography until each one has a
   real photo of that actual work. Same rhythm as .ri-hero__grid, one column. */
/* Centred to match .ri-head below it. Left-aligned, this sat hard against the
   left edge with the whole right half empty while every section heading under it
   was centred — two alignments on one page. The grid hero balances itself with an
   image; the solo hero has nothing on the right, so it centres instead. */
.ri-hero__solo { max-width: 62ch; margin-inline: auto; text-align: center; }
.ri-hero__solo .ri-actions,
.ri-hero__solo .ri-marks { justify-content: center; }
.ri-hero__solo h1,
.ri-hero__solo .ri-lede,
.ri-hero__solo p { margin-inline: auto; }

/* Quiet footnote under a section — used for the overflow list of covered towns
   that do not warrant their own page. */
.ri-note {
  max-width: 68ch;
  font-size: 0.93rem;
  color: var(--muted);
}
.ri-note a { color: var(--primary); }
.ri-hero__solo h1 { max-width: 26ch; }
.ri-hero__solo .ri-lede { max-width: 54ch; }

.ri-hero .ri-lede { max-width: 48ch; color: var(--ink-soft); }
.ri-hero p + p { color: var(--muted); font-size: 1rem; max-width: 48ch; }

.ri-hero__media {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.ri-hero__media img {
  display: block;
  width: 100%;
  /* Matches the source file exactly so nothing is cropped. The hero is now a
     1200x800 (3:2) image, which covers a 2x display at the ~526px it renders
     at; the previous 612px source was only 0.58x and visibly soft. */
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* A navy veil pulls the photograph onto the palette so it stops reading as a
   stock image dropped into a different colour scheme. */
.ri-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(140deg, rgba(18, 41, 61, 0.30) 0%, rgba(31, 92, 130, 0.12) 55%, rgba(184, 74, 50, 0.10) 100%);
  pointer-events: none;
}

/* Credential markers under the hero copy. */
.ri-marks {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 26px;
}

.ri-mark {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.79rem;
  white-space: nowrap;
  font-weight: 500;
  color: var(--ink);
  background-color: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 6px 13px 6px 10px;
}

.ri-mark::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background-color: var(--accent);
  flex: 0 0 auto;
}

/* The feature trio rides up over the join between hero and page. */
.ri-hero-cards { margin-top: clamp(-56px, -4vw, -34px); position: relative; z-index: 2; }

/* ---------- 10. Page header (inner pages) ------------------------------ */

.ri-pagehead {
  background-color: var(--wash);
  padding: clamp(48px, 4vw + 22px, 84px) 0 clamp(52px, 4vw + 24px, 88px);
  text-align: center;
}

.ri-pagehead h1 { margin: 0 auto 0.45em; max-width: 26ch; }
.ri-pagehead .ri-lede { margin: 0 auto; max-width: 60ch; color: var(--muted); }

/* ---------- 11. Numbered steps ----------------------------------------
   Numbering is used here and nowhere else, because this is the one place the
   order carries information: it is the actual sequence of a job. */

.ri-steps { counter-reset: ri-step; }

.ri-step { counter-increment: ri-step; }

.ri-step__no {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  margin-bottom: 20px;
  border-radius: 50%;
  border: 1.5px solid var(--primary-light);
  color: var(--primary);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
}

.ri-step__no::before { content: counter(ri-step); }

/* ---------- 12. Split panels (audience) -------------------------------- */

.ri-panel {
  display: flex;
  flex-direction: column;
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 34px 32px 30px;
  box-shadow: var(--shadow-sm);
  transition: transform .28s ease, box-shadow .28s ease;
}

.ri-panel:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }

.ri-panel h3 { font-size: 1.42rem; }

.ri-checks { margin: 4px 0; }

.ri-checks li {
  position: relative;
  padding-left: 30px;
  margin-bottom: 11px;
  color: var(--ink-soft);
  font-size: 0.965rem;
}

.ri-checks li::before {
  content: "";
  position: absolute;
  left: 3px; top: 0.52em;
  width: 12px; height: 6px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

/* ---------- 13. Prose (about) ------------------------------------------ */

.ri-prose { max-width: 66ch; }
.ri-prose p { font-size: 1.055rem; line-height: 1.72; }
.ri-prose > p:first-child { font-size: 1.16rem; color: var(--ink); }

.ri-pullquote {
  margin: 34px 0;
  padding: 4px 0 4px 26px;
  border-left: 3px solid var(--accent);
  font-family: var(--font-display);
  font-size: 1.24rem;
  line-height: 1.45;
  color: var(--ink);
}

.ri-factlist {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 2px;
  background-color: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
}

.ri-fact { background-color: var(--surface); padding: 24px 22px; }

.ri-fact__value {
  display: block;
  font-family: var(--font-display);
  font-size: 1.95rem;
  font-weight: 700;
  line-height: 1;
  color: var(--primary);
  margin-bottom: 7px;
}

.ri-fact__label {
  display: block;
  font-size: 0.83rem;
  line-height: 1.4;
  color: var(--muted);
}

/* ---------- 14. Testimonials ------------------------------------------- */

.ri-quote {
  display: flex;
  flex-direction: column;
  background-color: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 30px 28px 26px;
  box-shadow: var(--shadow-sm);
}

.ri-quote__stars { color: var(--accent-light); font-size: 0.85rem; letter-spacing: 2px; margin-bottom: 16px; }

.ri-quote blockquote {
  margin: 0 0 20px;
  font-size: 1rem;
  line-height: 1.62;
  color: var(--ink-soft);
}

.ri-quote figcaption {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-top: auto;
  font-size: 0.9rem;
}

.ri-quote figcaption img {
  width: 42px; height: 42px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}

.ri-quote__name { font-weight: 600; color: var(--ink); display: block; }
.ri-quote__where { color: var(--muted); font-size: 0.85rem; }

/* ---------- 15. Contact ------------------------------------------------ */

.ri-contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(26px, 3vw, 44px);
  align-items: stretch;
}

.ri-formcard,
.ri-mapcard {
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.ri-formcard { padding: 34px 32px; }

.ri-mapcard { overflow: hidden; min-height: 420px; padding: 0; }
.ri-mapcard iframe { display: block; width: 100%; height: 100%; min-height: 420px; border: 0; }

.ri-field { margin-bottom: 17px; }

.ri-field label {
  display: block;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
  margin-bottom: 7px;
}

.ri-field input,
.ri-field textarea {
  display: block;
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background-color: #fff;
  border: 1.5px solid var(--line);
  border-radius: 8px;
  padding: 12px 15px;
  transition: border-color .2s ease, box-shadow .2s ease;
}

.ri-field textarea { min-height: 148px; resize: vertical; }

.ri-field input::-webkit-input-placeholder,
.ri-field textarea::-webkit-input-placeholder { color: #93A4AE; }
.ri-field input::placeholder,
.ri-field textarea::placeholder { color: #93A4AE; }

.ri-field input:focus,
.ri-field textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(31, 92, 130, 0.14);
}

/* Honeypot. Positioned off-canvas rather than display:none, which some bots
   deliberately skip. */
.ri-hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.ri-formnote { font-size: 0.85rem; color: var(--muted); margin-top: 16px; }

.ri-status {
  border-radius: 9px;
  padding: 14px 18px;
  margin-bottom: 22px;
  font-size: 0.95rem;
  font-weight: 500;
}
.ri-status.ok  { background-color: #E3F1E6; color: #17452A; border: 1px solid #BFDFC7; }
.ri-status.err { background-color: #FBE7E4; color: #6E1F13; border: 1px solid #F0C7C0; }

/* Call / WhatsApp / Email cards above the form. */
.ri-method__value {
  display: block;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 5px;
  word-break: break-word;
}
.ri-method:hover .ri-method__value { color: var(--primary); }

/* ---------- 16. Partners ----------------------------------------------- */

.ri-partners__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 22px;
  align-items: stretch;
  max-width: 900px;
  margin: 0 auto;
}

.ri-partner {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 20px 24px;
  min-height: 98px;
  box-shadow: var(--shadow-sm);
}

.ri-partner img { max-height: 46px; width: auto; object-fit: contain; }

/* ---------- 17. Closing CTA -------------------------------------------- */

.ri-cta {
  background-color: var(--ink);
  color: var(--on-dark);
  text-align: center;
  padding: clamp(56px, 4vw + 30px, 92px) 0;
}

.ri-cta h2 { color: var(--on-dark); margin-bottom: 0.4em; }
.ri-cta p { color: var(--on-dark-soft); max-width: 54ch; margin: 0 auto 26px; }
.ri-cta .ri-actions { justify-content: center; }
.ri-cta .ri-eyebrow { color: var(--primary-light); }

/* ---------- 18. Footer ------------------------------------------------- */

.ri-footer {
  background-color: var(--ink);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--on-dark-soft);
  padding: 54px 0 34px;
  font-size: 0.92rem;
}

.ri-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) repeat(4, minmax(0, 0.85fr));
  gap: 34px;
  margin-bottom: 38px;
}

.ri-footer img { width: 200px; margin-bottom: 16px; }
.ri-footer h4 {
  color: var(--on-dark);
  font-family: var(--font-body);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.ri-footer a { color: var(--on-dark-soft); }
.ri-footer a:hover { color: #fff; }
.ri-footer li { margin-bottom: 9px; }
.ri-footer__blurb { max-width: 34ch; color: var(--on-dark-soft); }

.ri-footer__base {
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 22px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px 24px;
  font-size: 0.85rem;
  color: #8AA4B6;
}

/* ---------- 19. Scroll reveal -----------------------------------------
   Hiding is opt-in: nothing is transparent until reveal.js has confirmed it
   can run and adds .reveal-on to <html>. Previously .reveal was opacity:0 by
   default, so a blocked script left whole sections invisible. */

.reveal-on .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s ease, transform .6s ease;
}

.reveal-on .reveal.is-visible { opacity: 1; transform: none; }

/* ---------- 20. Utilities ---------------------------------------------- */

.ri-center { text-align: center; }
.ri-mt { margin-top: clamp(34px, 3vw, 52px); }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- 21. Responsive --------------------------------------------- */

@media (max-width: 991px) {
  .ri-header .navbar-collapse {
    padding: 14px 0 8px;
    border-top: 1px solid var(--line-soft);
    margin-top: 12px;
  }
  .ri-header .navbar-nav { gap: 2px; }
  .ri-header .nav-link { padding: 10px 12px; }
  .ri-header .nav-item.active > .nav-link::after { display: none; }
  .ri-header .ri-nav-cta { margin: 12px 0 0; }
  .ri-header .ri-nav-cta .ri-btn { width: 100%; }

  .ri-header .ri-drop {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    min-width: 0;
    margin: 0;
    padding: 0 0 4px 14px;
    background: none;
    border: 0;
    box-shadow: none;
  }
  .ri-header .ri-drop a { padding: 8px 12px; font-size: 0.95rem; color: var(--muted); }
  .ri-header .ri-drop-arrow { display: none; }

  .ri-hero__grid { grid-template-columns: 1fr; }
  .ri-hero h1, .ri-hero .ri-lede { max-width: none; }

  /* The photo used to be order:-1 here, which put it above the h1 on a phone.
     That pushed the proposition below the fold: anyone arriving from Google on
     mobile saw a laptop and no reason to stay. Headline first, picture after,
     and the picture is a band rather than a wall so the buttons stay visible. */
  .ri-hero__media { order: 0; margin-top: 22px; }
  .ri-hero__media img { aspect-ratio: 16 / 9; object-fit: cover; object-position: center 40%; }

  .ri-contact__grid { grid-template-columns: 1fr; }
  .ri-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ri-footer__grid > :first-child { grid-column: 1 / -1; }
}

@media (max-width: 767px) {
  body { font-size: 16px; }
  .ri-topbar__inner { justify-content: center; }
  .ri-hero-cards { margin-top: clamp(-40px, -5vw, -26px); }
  .ri-formcard { padding: 26px 22px; }
  .ri-mapcard, .ri-mapcard iframe { min-height: 300px; }
  .ri-footer__grid { grid-template-columns: 1fr; gap: 26px; }
}

@media (max-width: 575px) {
  .ri-hero-cards { margin-top: 0; }
  .ri-hero { padding-bottom: clamp(48px, 6vw, 64px); }
  .ri-card { padding: 26px 22px 24px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    -webkit-animation-duration: 0.01ms !important;
            animation-duration: 0.01ms !important;
    -webkit-transition-duration: 0.01ms !important;
            transition-duration: 0.01ms !important;
  }
  .reveal-on .reveal { opacity: 1; -webkit-transform: none; transform: none; }
}

/* ---------- 22. Layout utilities used by the generated markup ----------- */

.ri-align-start { align-items: start; }
.ri-gap-wide { gap: clamp(34px, 4vw, 64px); }
.ri-mb { margin-bottom: 26px; }
.ri-actions--center { justify-content: center; }
.ri-contact__methods { margin-bottom: 34px; }
.ri-optional { font-weight: 400; color: var(--muted); }

/* A whole card that is itself a link: kill the inherited underline colour
   change on the body copy so only the value reacts to hover. */
a.ri-card { color: inherit; }
a.ri-card:hover { color: inherit; }
a.ri-card:hover p { color: var(--muted); }

/* ---------- 23. Fixed-track grids ---------------------------------------
   .ri-grid--2 uses auto-fit, which is right for two panels but makes three
   tracks when given four items, leaving an orphan on a second row. These two
   pin the track count where the content count is known. */

.ri-grid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* About: the prose column carries the weight, the aside supports it. */
.ri-grid--prose { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }

@media (max-width: 900px) {
  .ri-grid--pair,
  .ri-grid--prose { grid-template-columns: 1fr; }
}

/* ==========================================================================
   24. Standalone layout — replaces Bootstrap and FontAwesome
   --------------------------------------------------------------------------
   The site used bootstrap.css (192KB) and font-awesome (31KB + ~80KB of font
   files) for a grid container, a navbar toggle and two icons, and jquery
   3.4.1 + bootstrap.js (220KB) to open that toggle. jQuery 3.4.1 is affected
   by CVE-2020-11022 and CVE-2020-11023, both fixed in 3.5.0, so it was also
   a live vulnerability being served for no functional reason. All four are
   gone; what they were actually doing is below.
   ========================================================================== */

.container {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ---- Navbar ---- */

.ri-header .navbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0;
}

/* No gap here. The base gap is set once, higher up, so the 992-1199px and mobile
   media queries can still tighten it. A duplicate gap in this block sits AFTER both
   of them at equal specificity and silently cancels them. */
.ri-header .navbar-nav {
  display: flex;
  align-items: center;
  margin-left: auto;
}

.ri-header .navbar-collapse { display: flex; flex-grow: 1; }

.ri-header .navbar-toggler { display: none; }

.ri-topbar .ri-ico-inline {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  fill: none;
  stroke: var(--accent-light);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (max-width: 991px) {
  .ri-header .navbar { flex-wrap: nowrap; }
  .ri-header .navbar-toggler { display: block; }

  .ri-header .navbar-collapse {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
  }
  .ri-header .navbar-collapse.is-open { display: flex; }

  .ri-header .navbar-nav {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    margin-left: 0;
  }
  .ri-header .nav-link { display: block; }
}

@media (max-width: 420px) {
  .container { padding: 0 18px; }
  .ri-header .navbar-brand img { width: 200px; }
}

/* ---------- 25. Opening hours ------------------------------------------- */

/* Pushed left so the contact links stay right-aligned. */
.ri-topbar__hours { margin-right: auto; color: var(--on-dark-soft); }

.ri-hours {
  margin-top: 14px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}
.ri-hours strong { color: var(--ink); }

@media (max-width: 700px) {
  /* Two contact links plus hours is too much for a phone-width bar; the hours
     are repeated in the contact section and the footer, so this is not a loss. */
  .ri-topbar__hours { display: none; }
}

/* ==========================================================================
   26. Web design service page
   ========================================================================== */

/* ---- Package cards ---- */
.ri-pack { position: relative; }
.ri-pack--feature { border-color: var(--accent); border-width: 2px; }

.ri-pack__flag {
  position: absolute; top: -11px; left: 24px;
  background: var(--accent); color: #fff;
  font-size: 0.66rem; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; padding: 4px 11px; border-radius: 100px;
}

.ri-pack__price {
  font-family: var(--font-display);
  font-size: 2.15rem; font-weight: 700; line-height: 1;
  color: var(--ink); margin: 2px 0 3px;
}
.ri-pack__price small {
  display: block; font-family: var(--font-body);
  font-size: 0.78rem; font-weight: 500; letter-spacing: 0.04em;
  color: var(--muted); margin-bottom: 6px;
}
.ri-pack__note { font-size: 0.86rem; color: var(--muted); margin-bottom: 16px; }
.ri-pack ul { margin: 0 0 4px; font-size: 0.93rem; }
.ri-pack li { position: relative; padding-left: 24px; margin-bottom: 9px; color: var(--ink-soft); }
.ri-pack li::before {
  content: ""; position: absolute; left: 2px; top: 0.52em;
  width: 11px; height: 6px;
  border-left: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

/* ---- Portfolio ---- */
.ri-work {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform .28s ease, box-shadow .28s ease;
}
.ri-work:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }

.ri-work__shot {
  display: block; width: 100%; aspect-ratio: 900 / 562;
  object-fit: cover; object-position: top center;
  border-bottom: 1px solid var(--line-soft);
  background: var(--wash);
}
.ri-work__body { padding: 22px 22px 20px; display: flex; flex-direction: column; flex: 1; }
.ri-work__body h3 { margin-bottom: 0.35em; }
.ri-work__body p { color: var(--muted); font-size: 0.93rem; }
.ri-work__tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.ri-work__tag {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--primary);
  background: var(--wash); border-radius: 100px; padding: 3px 9px;
}

/* ---- Questions ---- */
.ri-qa { max-width: 70ch; margin: 0 auto; }
.ri-qa__item { border-bottom: 1px solid var(--line-soft); padding: 20px 0; }
.ri-qa__item:last-child { border-bottom: 0; }
.ri-qa__item h3 { margin-bottom: 0.4em; font-family: var(--font-display); font-size: 1.12rem; }
.ri-qa__item p { margin-bottom: 0; }

@media (max-width: 991px) {
  /* Five nav items plus the call button need the room. */
  .ri-header .navbar-brand img { width: 212px; }
}

/* ---- Fasthosts: their official asset ships filled white for dark grounds, so
   it is coloured here via currentColor rather than being redrawn. ---- */
.ri-partner--svg { color: var(--ink); }

.ri-partner__svg {
  width: 100%;
  max-width: 150px;
  height: auto;
  fill: currentColor;
  display: block;
}

@media (max-width: 480px) {
  .ri-partner__svg { max-width: 130px; }
}
