/* ==========================================================================
   A1Hosting — public site stylesheet
   Hand written, no framework, no webfont download. Every colour is a token so
   dark mode is a token remap rather than a second stylesheet.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens */

:root {
  /* Brand - Microsoft / Azure blue, to match the A1Hosting logo, whose two
     strokes are #3799e4 and #2973ac and so sit inside this family already.

     Picked against measured contrast rather than by eye:
       --brand-500 #0078d4  4.53:1 on white, and white text on it is also
                            4.53:1, so it works as a button ground and as text
       --brand-700 #005a9e  7.10:1 on white; the dark end of the brand
                            gradients, and blue text on a brand tint

       The ramp is the same in dark mode. Blue used as prose goes through
       --brand-text and --brand-on-tint, which do move between themes. */
  --brand-050: #eff6fc;
  --brand-100: #deecf9;
  --brand-200: #c7e0f4;
  --brand-500: #0078d4;
  --brand-600: #106ebe;
  --brand-700: #005a9e;

  /* Brand text on a surface that is light in BOTH themes — a white button,
     the light hero slide. Those grounds do not change, so this colour must
     not either, which is why it is separate from the ramp above. */
  --brand-ink: #005a9e;

  /* Blue used as prose, on the page's own background. Splits from the ramp
     because Azure at body size does not clear 4.5:1 on a dark ground, and
     the ramp itself no longer changes between themes. */
  --brand-text: #106ebe;

  /* Blue used as prose on a --brand-050 tint. That surface inverts between
     themes, so this has to invert with it. */
  --brand-on-tint: #005a9e;
  --warn-ink:   #92400e;
  --danger-ink: #991b1b;

  /* The label on a filled button. White here because a filled button is a
     dark blue in the light theme; the dark blocks flip it, because there the
     same button is a light blue. */
  --btn-fill-fg: #ffffff;

  /* Tech accent - Azure's accent cyan. Carries the technical register: the far
     stop of the hero gradient, stat figures, the rule under a heading, the
     "best value" badge. Used sparingly; it is a highlight, not a second brand.

     --tech-300 #50e6ff is 12.7:1 on the dark hero but only 1.5:1 on white, so
     it is for dark grounds only. Text on a light background uses --tech-700. */
  --tech-050: #e8fbff;
  --tech-100: #ccf5ff;
  --tech-300: #79ecff;
  --tech-400: #50e6ff;
  --tech-500: #00b7de;
  --tech-600: #0091b0;
  --tech-700: #006e8a;

  /* Accent for the tech-art illustrations. Split per theme because the
     cyan above is a dark-ground colour: measured against the --brand-050
     panel these sit on, --tech-400 is 10.93:1 in dark but only 1.37:1 in
     light, and non-text artwork needs 3:1. --tech-600 gives 3.39:1 here,
     and the dark blocks below swap in --tech-400. Marks drawn on top of
     the accent use --paper-dark, which clears both (5.12 and 12.71). */
  --art-accent: var(--tech-600);

  /* Success stays green so a tick never competes with the accent for meaning. */
  /* Icon-weight green: 3.7:1 on white, which clears the 3:1 that non-text UI
     needs. Text uses --accent-700 instead. */
  --accent-500: #059669;
  --accent-700: #047857;
  --accent-050: #ecfdf5;
  --warn-500:   #f59e0b;
  --warn-050:   #fffbeb;
  --danger-500: #e11d48;
  --danger-050: #fff1f2;

  /* Near-neutral grey, not blue-grey. The old slate ramp tinted every surface and
     border blue, which is most of why the page read as "all blue" even in places
     where nothing was actually brand-coloured. */
  --ink-900: #0e1116;
  --ink-800: #1a1e26;
  --ink-700: #383e49;
  --ink-500: #6a7280;
  --ink-400: #98a0ac;
  --ink-300: #cdd2da;

  /* Text on a dark surface. Named separately so dark bands stop hardcoding a
     blue-grey and can stay neutral. */
  --on-dark-100: #ffffff;
  --on-dark-300: #e4e7ec;
  --on-dark-500: #c9ced7;
  --on-dark-700: #98a0ac;

  --paper:     #ffffff;
  --paper-alt: #f7f8fa;
  --paper-dark:#0d1117;
  --line:      #e5e8ec;

  /* Form control edges, which WCAG 1.4.11 asks to clear 3:1 — --line is
     1.23:1 here, fine for a card rule and far too faint for the boundary
     of something you are meant to click into. Kept separate so cards and
     table rules are not darkened along with it. */
  --field-line: #8a929e;

  --radius:    12px;
  --radius-sm: 8px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgb(15 23 42 / .06), 0 1px 3px rgb(15 23 42 / .10);
  --shadow-2: 0 4px 12px rgb(15 23 42 / .08);
  --shadow-3: 0 12px 32px rgb(15 23 42 / .12);

  --container: 1200px;
  --gap: 24px;

  --step--1: clamp(.83rem, .8rem + .15vw, .9rem);
  --step-0:  clamp(1rem, .96rem + .2vw, 1.05rem);
  --step-1:  clamp(1.2rem, 1.1rem + .5vw, 1.4rem);
  --step-2:  clamp(1.5rem, 1.3rem + 1vw, 2rem);
  --step-3:  clamp(1.9rem, 1.5rem + 2vw, 2.9rem);
  --step-4:  clamp(2.3rem, 1.7rem + 3.2vw, 3.8rem);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
          Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

/* Dark mode: remap the greyscale and paper tokens only.
   
   Written out twice on purpose, because CSS has no way to share a declaration
   list between two selectors:
   
     1. the visitor's device asks for dark AND they have not chosen light
     2. the visitor (or the admin default) has explicitly chosen dark
   
   Keep the two lists identical. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {

      /* The brand and status ramps, remapped for a dark ground.

         Without these the light-theme values carry over and fail: body links
         measured 3.60:1 and badge text 2.29:1 against the dark surfaces they
         actually sit on. Every value below clears 4.5:1 on both --paper and
         --paper-alt. */
      /* The brand ramp is deliberately NOT remapped here: one Azure in both
         themes. Blue used as text goes through --brand-text and
         --brand-on-tint instead, which is where the contrast problem actually
         lives — a filled button or a gradient has no such problem, and
         repainting those was what made the site look like two brands. */
      --brand-text:    #7cc4ff;
      --brand-on-tint: #9dd4ff;
      --accent-500: #34d399;
      --accent-700: #6ee7b7;
      --warn-500:   #fbbf24;
      --danger-500: #fb7185;

      /* Tinted surfaces to match, so a status badge is a dark tint of its own
         hue rather than a cream rectangle glowing on a dark page. */
      --accent-050: #062a1e;
      --warn-050:   #2c2007;
      --danger-050: #2e0d16;

      /* A filled button is a light surface here, so its label goes dark. */
      --btn-fill-fg: #ffffff;
      --warn-ink:   #fcd34d;
      --danger-ink: #fda4af;

      --art-accent: var(--tech-400);

    --ink-900: #f4f6f8;
    --ink-800: #e4e7ec;
    --ink-700: #c9ced7;
    --ink-500: #949cab;
    --ink-400: #6b7382;
    --ink-300: #414855;

    --paper:     #0d1117;
    --paper-alt: #151a22;
    --line:      #262c36;
    --field-line: #5a6472;

    /* Tinted surfaces keep a trace of their hue so a brand-tinted panel still reads
       as brand-tinted, but at dark-surface luminance. */
    --brand-050: #0b2233;
    --brand-100: #12304a;

    --tech-050:   #07272f;
    --accent-050: #0d2a20;
    --warn-050:   #2e2409;
    --danger-050: #331219;

    --shadow-1: 0 1px 2px rgb(0 0 0 / .4);
    --shadow-2: 0 4px 12px rgb(0 0 0 / .45);
    --shadow-3: 0 12px 32px rgb(0 0 0 / .5);
  }
}

:root[data-theme="dark"] {

      /* The brand and status ramps, remapped for a dark ground.

         Without these the light-theme values carry over and fail: body links
         measured 3.60:1 and badge text 2.29:1 against the dark surfaces they
         actually sit on. Every value below clears 4.5:1 on both --paper and
         --paper-alt. */
      /* The brand ramp is deliberately NOT remapped here: one Azure in both
         themes. Blue used as text goes through --brand-text and
         --brand-on-tint instead, which is where the contrast problem actually
         lives — a filled button or a gradient has no such problem, and
         repainting those was what made the site look like two brands. */
      --brand-text:    #7cc4ff;
      --brand-on-tint: #9dd4ff;
      --accent-500: #34d399;
      --accent-700: #6ee7b7;
      --warn-500:   #fbbf24;
      --danger-500: #fb7185;

      /* Tinted surfaces to match, so a status badge is a dark tint of its own
         hue rather than a cream rectangle glowing on a dark page. */
      --accent-050: #062a1e;
      --warn-050:   #2c2007;
      --danger-050: #2e0d16;

      /* A filled button is a light surface here, so its label goes dark. */
      --btn-fill-fg: #ffffff;
      --warn-ink:   #fcd34d;
      --danger-ink: #fda4af;

      --art-accent: var(--tech-400);

    --ink-900: #f4f6f8;
    --ink-800: #e4e7ec;
    --ink-700: #c9ced7;
    --ink-500: #949cab;
    --ink-400: #6b7382;
    --ink-300: #414855;

    --paper:     #0d1117;
    --paper-alt: #151a22;
    --line:      #262c36;
    --field-line: #5a6472;

    /* Tinted surfaces keep a trace of their hue so a brand-tinted panel still reads
       as brand-tinted, but at dark-surface luminance. */
    --brand-050: #0b2233;
    --brand-100: #12304a;

    --tech-050:   #07272f;
    --accent-050: #0d2a20;
    --warn-050:   #2e2409;
    --danger-050: #331219;

    --shadow-1: 0 1px 2px rgb(0 0 0 / .4);
    --shadow-2: 0 4px 12px rgb(0 0 0 / .45);
    --shadow-3: 0 12px 32px rgb(0 0 0 / .5);
}

/* ---------------------------------------------------------------- reset */

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

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-700);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
svg { flex: none; }

/* icon() emits a viewBox-only <svg class="icon">. Without a size it would stretch to
   fill whatever box it lands in, so give every icon a sane default; the component
   rules further down (.feature__icon svg, .svc-card__icon svg, ...) override it. */
.icon { width: 1.15em; height: 1.15em; display: inline-block; vertical-align: -.15em; }

h1, h2, h3, h4 { color: var(--ink-900); line-height: 1.2; margin: 0 0 .5em; font-weight: 700; letter-spacing: -.02em; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand-text); text-decoration: none; }
a:hover { text-decoration: underline; }

ul, ol { margin: 0 0 1em; padding-left: 1.25em; }
li + li { margin-top: .25em; }

hr { border: 0; border-top: 1px solid var(--line); margin: 2rem 0; }

:focus-visible {
  outline: 3px solid var(--brand-500);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Visually hidden, still read aloud.

   `clip` is the legacy property and it does not stop the element taking part
   in layout: absolutely positioned with white-space: nowrap, a long label
   sitting inside a wide horizontally-scrolling table resolved its position
   against the page rather than the wrapper and pushed the document 226px
   sideways on /pricing and 274px on /web-hosting. Every phone visitor could
   drag those pages into an empty band.

   clip-path with a zero-size box removes it from the overflow calculation,
   and the containment rule below stops it escaping its wrapper at all. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* An absolutely positioned child resolves against its nearest POSITIONED
   ancestor. These wrappers were static, so their hidden labels escaped to
   the page box and widened it. Making them positioned confines anything
   inside them, which is what an overflow container should do anyway. */
.matrix__wrap,
.table--wrap,
.table-scroll,
.tbl-wrap { position: relative; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--brand-600); color: #fff; padding: .75rem 1.25rem;
  border-radius: 0 0 var(--radius-sm) 0; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* Honeypot field: off-screen rather than display:none, which some bots detect. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------------------------------------------------------------- layout */

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: clamp(16px, 4vw, 28px); }

.section { padding: clamp(48px, 7vw, 88px) 0; }
.section--alt { background: var(--paper-alt); }
.section--tight { padding: clamp(32px, 4vw, 48px) 0; }
.section--dark { background: var(--paper-dark); color: var(--on-dark-500); }
.section--dark h1, .section--dark h2, .section--dark h3 { color: #fff; }

.section__head { max-width: 46rem; margin: 0 auto clamp(28px, 4vw, 48px); text-align: center; }
.section__head--left { margin-inline: 0; text-align: left; }

.eyebrow {
  display: inline-block; font-size: var(--step--1); font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--brand-text);
  margin-bottom: .5rem;
}

.h1 { font-size: var(--step-4); }
.h2 { font-size: var(--step-3); }
.h3 { font-size: var(--step-2); }
.lede { font-size: var(--step-1); color: var(--ink-500); }

.grid { display: grid; gap: var(--gap); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }

.text-center { text-align: center; }

/* ---------------------------------------------------------------- buttons */

.btn {
  --btn-bg: var(--brand-600);
  --btn-fg: var(--btn-fill-fg);
  --btn-bd: transparent;
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .8rem 1.4rem; border: 1px solid var(--btn-bd); border-radius: var(--radius-sm);
  background: var(--btn-bg); color: var(--btn-fg);
  font: inherit; font-weight: 600; line-height: 1.2; text-align: center;
  cursor: pointer; text-decoration: none;
  transition: transform .12s ease, box-shadow .12s ease, background-color .12s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--shadow-2); }
.btn:active { transform: none; box-shadow: none; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .55; pointer-events: none; }

.btn--primary { --btn-bg: var(--brand-600); }
.btn--primary:hover { --btn-bg: var(--brand-700); }
.btn--accent  { --btn-bg: var(--accent-500); }
.btn--ghost   { --btn-bg: transparent; --btn-fg: var(--brand-600); --btn-bd: var(--line); }
.btn--ghost:hover { --btn-bg: var(--brand-050); }
.btn--light   { --btn-bg: #fff; --btn-fg: var(--brand-ink); }
.btn--danger  { --btn-bg: var(--danger-500); }
.btn--sm { padding: .55rem 1rem; font-size: var(--step--1); }
.btn--lg { padding: 1rem 1.9rem; font-size: var(--step-1); }
.btn--block { width: 100%; }

.link-arrow { display: inline-flex; align-items: center; gap: .35rem; font-weight: 600; }
.link-arrow svg { width: 1em; height: 1em; transition: transform .15s ease; }
.link-arrow:hover svg { transform: translateX(3px); }

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-1);
}
.card__body { padding: clamp(20px, 3vw, 28px); }
.card__head { padding: 18px clamp(20px, 3vw, 28px); border-bottom: 1px solid var(--line); }

.badge {
  display: inline-block; padding: .25em .7em; border-radius: var(--radius-pill);
  font-size: var(--step--1); font-weight: 700; line-height: 1.5;
  background: var(--brand-050); color: var(--brand-on-tint);
}
.badge--best {
  /* Ends on cyan-700, not cyan-500: white text needs 4.5:1 and the lighter cyan
     only reached 3.7:1. */
  background: linear-gradient(120deg, var(--brand-600), var(--tech-700));
  color: #fff; text-transform: uppercase; letter-spacing: .05em;
  box-shadow: 0 2px 10px rgb(79 70 229 / .35);
}
.badge--warn { background: var(--warn-050); color: var(--warn-ink); }
.badge--danger { background: var(--danger-050); color: var(--danger-ink); }
.badge--muted { background: var(--paper-alt); color: var(--ink-500); }

.pill {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .4rem .85rem; border-radius: var(--radius-pill);
  background: var(--paper-alt); border: 1px solid var(--line);
  font-size: var(--step--1); font-weight: 600; color: var(--ink-700);
}

/* ---------------------------------------------------------------- promo bar */

.promo-bar {
  background: linear-gradient(90deg, var(--brand-700), var(--brand-500));
  color: #fff; font-size: var(--step--1); font-weight: 600; text-align: center;
}
.promo-bar .container { padding-block: .55rem; }
.promo-bar a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }

/* ---------------------------------------------------------------- header */

.site-header { position: sticky; top: 0; z-index: 100; background: var(--paper); }
.site-header.is-stuck { box-shadow: var(--shadow-2); }

.site-header__topbar {
  background: var(--paper-alt); border-bottom: 1px solid var(--line);
  font-size: var(--step--1);
}
.site-header__topbar-inner { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: center; justify-content: space-between; padding-block: .5rem; }

.topbar-contact, .topbar-links { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; list-style: none; margin: 0; padding: 0; }
.topbar-contact li, .topbar-links li { margin: 0; display: flex; align-items: center; gap: .4rem; }
.topbar-contact a, .topbar-links a { color: var(--ink-500); }
.topbar-contact a:hover, .topbar-links a:hover { color: var(--brand-text); }
.topbar-contact svg, .topbar-links svg { width: 1em; height: 1em; color: var(--brand-500); }
.topbar-links__strong { font-weight: 600; color: var(--ink-700) !important; }

.site-header__bar { border-bottom: 1px solid var(--line); background: var(--paper); }
.site-header__bar-inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 68px; }

.logo, .footer-logo { display: inline-flex; align-items: center; gap: .6rem; font-weight: 800; font-size: 1.25rem; color: var(--ink-900); letter-spacing: -.03em; }
.logo:hover, .footer-logo:hover { text-decoration: none; }
.logo__mark { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--brand-600); color: #fff; }
.logo__mark svg { width: 20px; height: 20px; }
.footer-logo { color: #fff; }

/* --- navigation */

.nav { display: flex; align-items: center; gap: 1.5rem; }
.nav__list { display: flex; align-items: center; gap: .25rem; list-style: none; margin: 0; padding: 0; }
.nav__item { margin: 0; position: relative; }

.nav__link {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .6rem .7rem; border-radius: var(--radius-sm);
  font-weight: 600; font-size: .95rem; color: var(--ink-700);
  background: none; border: 0; cursor: pointer; font-family: inherit;
}
.nav__link:hover { color: var(--brand-on-tint); background: var(--brand-050); text-decoration: none; }
.nav__link--active { color: var(--brand-text); }
.nav__chev { width: .8em; height: .8em; transition: transform .15s ease; }
.nav__item.is-open .nav__chev { transform: rotate(180deg); }

.dropdown {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  min-width: 14rem; padding: .5rem; margin: 0; list-style: none;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-3);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .14s ease, transform .14s ease, visibility .14s;
}
.dropdown li { margin: 0; }
.nav__item.has-dropdown:hover .dropdown,
.nav__item.is-open .dropdown { opacity: 1; visibility: visible; transform: none; }

.dropdown__link { display: block; padding: .55rem .75rem; border-radius: var(--radius-sm); font-weight: 500; color: var(--ink-700); }
.dropdown__link:hover, .dropdown__link.is-active { background: var(--brand-050); color: var(--brand-on-tint); text-decoration: none; }

/* One row: light/dark, Help, Sign in, Cart.
   align-items matters more than it looks. Without it flex defaults to
   `stretch`, and the light/dark switch carries an explicit height (1.9rem)
   which stretch cannot override — so it stayed its own size and sat against the
   top of the row while Help and Sign in grew taller around it. `stretch` also
   pulled the Sign in button, which has a visible 1px border, to the full row
   height, making it read as a different size from its borderless neighbours.
   Centring fixes both at once.
   nowrap is already the flex default; it is stated because these four must
   never break onto a second line. */
.nav__cta {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: .5rem;
}

/* flex: none on the children, because nowrap on the container is only half
   the job. A flex item may still SHRINK below its content width, down to
   min-content — and min-content for "Sign in" is the width of "Sign", so at
   a crowded width the button kept its single line and broke its label onto
   two instead. Adding the light/dark switch to this row is what pushed it
   over. flex: none stops the shrinking; the nowrap below stops the wrap even
   if something later forces a narrower box. */
.nav__cta > * { flex: none; }
.nav__cta .btn { white-space: nowrap; }

.nav__toggle { display: none; }
.nav__scrim { display: none; }

/* --- mobile nav (checkbox-driven so it works without JS) */

@media (max-width: 991px) {
  .hide-sm { display: none; }

  .nav__toggle {
    display: grid; place-items: center; width: 44px; height: 44px;
    border: 1px solid var(--field-line); border-radius: var(--radius-sm);
    cursor: pointer; background: var(--paper);
  }
  .nav__toggle-bars, .nav__toggle-bars::before, .nav__toggle-bars::after {
    content: ""; display: block; width: 20px; height: 2px; border-radius: 2px;
    background: var(--ink-700); transition: transform .18s ease, opacity .18s ease;
  }
  .nav__toggle-bars { position: relative; }
  .nav__toggle-bars::before { position: absolute; top: -6px; }
  .nav__toggle-bars::after  { position: absolute; top: 6px; }

  #nav-toggle:checked ~ .nav__toggle .nav__toggle-bars { background: transparent; }
  #nav-toggle:checked ~ .nav__toggle .nav__toggle-bars::before { transform: translateY(6px) rotate(45deg); }
  #nav-toggle:checked ~ .nav__toggle .nav__toggle-bars::after  { transform: translateY(-6px) rotate(-45deg); }

  .nav {
    position: fixed; inset: 0 0 0 auto; z-index: 120;
    width: min(88vw, 22rem); padding: 5rem 1.25rem 2rem;
    flex-direction: column; align-items: stretch; gap: 1rem;
    background: var(--paper); border-left: 1px solid var(--line);
    box-shadow: var(--shadow-3);
    transform: translateX(100%); transition: transform .22s ease;
    overflow-y: auto;
  }
  #nav-toggle:checked ~ .nav { transform: none; }

  .nav__list { flex-direction: column; align-items: stretch; gap: .15rem; }
  .nav__link { padding: .8rem .9rem; font-size: 1.05rem; justify-content: space-between; width: 100%; }

  .dropdown {
    position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; border-left: 2px solid var(--line);
    border-radius: 0; margin-left: .9rem; padding: .15rem 0 .35rem .5rem;
    display: none;
  }
  .nav__item.is-open .dropdown { display: block; }

  .nav__cta { flex-direction: column; margin-top: auto; padding-top: 1rem; border-top: 1px solid var(--line); }
  .nav__cta .btn { width: 100%; }

  .nav__scrim { display: block; position: fixed; inset: 0; z-index: 110; background: rgb(15 23 42 / .5); opacity: 0; visibility: hidden; transition: opacity .2s ease, visibility .2s; }
  #nav-toggle:checked ~ .nav__scrim { opacity: 1; visibility: visible; }
}

/* ---------------------------------------------------------------- hero */

.hero { position: relative; overflow: hidden; background: var(--paper-dark); color: var(--on-dark-500); }
.hero__slides { position: relative; }

/* The slide is the coloured band; the grid lives on the inner container so the
   copy still respects the site gutter. */
.hero__slide { padding: clamp(48px, 7vw, 96px) 0 clamp(64px, 8vw, 108px); }

.hero__slide-inner {
  display: grid; gap: clamp(24px, 4vw, 56px); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .hero__slide-inner { grid-template-columns: 1.15fr .85fr; } }

/* Slides stack; only the active one is shown. Without JS the first is visible. */
.hero__slide[hidden] { display: none; }

.hero__slide--brand {
  position: relative;
  background:
    radial-gradient(1200px 560px at 8% -20%, rgb(99 102 241 / .85), transparent 62%),
    radial-gradient(900px 500px at 92% 8%, rgb(6 182 212 / .48), transparent 64%),
    linear-gradient(135deg, #312e81 0%, #1e1b4b 55%, #0d1117 100%);
}
/* Fine grid: reads as infrastructure, and costs nothing to load. Faded out
   downward so it never fights the copy. */
.hero__slide--brand::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(rgb(255 255 255 / .055) 1px, transparent 1px),
    linear-gradient(90deg, rgb(255 255 255 / .055) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(75% 65% at 50% 0%, #000 35%, transparent 100%);
          mask-image: radial-gradient(75% 65% at 50% 0%, #000 35%, transparent 100%);
}
.hero__slide--brand > * { position: relative; z-index: 1; }
.hero__slide--dark  { background: linear-gradient(135deg, #0d1117 0%, #1b202a 100%); }
.hero__slide--light { background: linear-gradient(135deg, var(--brand-050) 0%, #fff 100%); color: var(--ink-700); }
.hero__slide--light .hero__kicker { color: var(--brand-ink); }
.hero__slide--light .hero__headline, .hero__slide--light .hero__sub { color: var(--ink-900); }

.hero__copy { max-width: 40rem; }
.hero__kicker { font-size: var(--step-1); font-weight: 600; color: var(--tech-300); margin-bottom: .25rem; }
.hero__headline { font-size: var(--step-4); color: #fff; margin-bottom: .5rem; }
.hero__sub { font-size: var(--step-1); color: var(--on-dark-500); margin-bottom: 1.25rem; }

.hero__promo { display: flex; flex-direction: column; gap: .35rem; margin-bottom: 1.5rem; }
.hero__promo span { display: inline-flex; align-items: center; gap: .5rem; font-weight: 600; color: #fff; }
.hero__promo svg { width: 1.1em; height: 1.1em; color: var(--accent-500); }

.hero__bullets { display: grid; gap: .4rem .9rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); list-style: none; padding: 0; margin: 0 0 1.5rem; }
.hero__bullets li { display: flex; align-items: flex-start; gap: .5rem; margin: 0; color: var(--on-dark-300); }
.hero__bullets svg { width: 1.1em; height: 1.1em; margin-top: .25em; color: var(--accent-500); }

.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
.hero__price { display: flex; align-items: baseline; gap: .3rem; color: #fff; }
.hero__price-prefix { font-size: var(--step--1); color: #bfdbfe; }
.hero__price-amount { font-size: var(--step-3); font-weight: 800; letter-spacing: -.03em; }
.hero__price-suffix { font-size: var(--step-0); color: #bfdbfe; }

/* Decorative only, so it is hidden entirely on small screens rather than
   pushing the copy down. */
.hero__media { display: none; }
@media (min-width: 900px) {
  .hero__media { display: grid; place-items: center; }
  .hero__media img { border-radius: var(--radius-lg); box-shadow: var(--shadow-3); }
}
/* A viewBox-only SVG will otherwise stretch to fill the grid cell. */
.hero__glyph { width: min(100%, 340px); height: auto; aspect-ratio: 1; color: rgb(255 255 255 / .22); }
.hero__slide--light .hero__glyph { color: rgb(79 70 229 / .18); }

/* The dots used to sit below the slide, on the hero base colour, which left a
   flat dark strip under the gradient with a hard edge across it. Float them over
   the bottom of the slide instead so the coloured band ends where it looks like
   it should. */
.hero__slides { position: relative; }
/* ------------------------------------------------------- hero: the controls */

/* The nav bar holds the pills and the play control together, so they read as
   one set rather than two things that happen to be near each other. */
.hero__nav {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 1.15rem;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .9rem;
}

.hero__dots {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.hero__dots li { margin: 0; }

/* Pills, not dots. The inactive ones are short; the active one widens to make
   room for a fill that runs for the length of the interval, so the slider says
   how long it has before it moves rather than moving without warning. */
.hero__dot {
  position: relative;
  display: block;
  width: 14px;
  height: 5px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill, 999px);
  background: rgb(255 255 255 / .32);
  cursor: pointer;
  overflow: hidden;
  transition: width .32s cubic-bezier(.4, 0, .2, 1), background-color .2s ease;
}

.hero__dot:hover { background: rgb(255 255 255 / .55); }

.hero__dot:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.hero__dot.is-active {
  width: 42px;
  background: rgb(255 255 255 / .3);
}

/* The fill is a child rather than a background-position animation, so it can be
   paused and resumed on hover without losing its place. */
.hero__dot-fill {
  position: absolute;
  inset: 0;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: #fff;
  border-radius: inherit;
}

.hero__dot.is-active .hero__dot-fill { transform: scaleX(1); }

@keyframes hero-dot-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* Play / pause. A hero that moves on its own and cannot be stopped is a real
   problem for anyone who reads slowly, so this is a control, not decoration. */
.hero__playpause {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid rgb(255 255 255 / .35);
  border-radius: 50%;
  background: rgb(255 255 255 / .12);
  color: #fff;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease;
}

.hero__playpause:hover {
  background: rgb(255 255 255 / .25);
  border-color: rgb(255 255 255 / .6);
}

.hero__playpause:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Two bars for pause, drawn with a border so there is no icon to load. */
.hero__playpause-icon {
  width: 8px;
  height: 9px;
  border-left: 2.5px solid currentColor;
  border-right: 2.5px solid currentColor;
}

/* One triangle for play. */
.hero__playpause.is-paused .hero__playpause-icon {
  width: 0;
  height: 0;
  border: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 8px solid currentColor;
  margin-left: 2px;
}

/* ------------------------------------------------------- hero: the arrows */

.hero__arrow {
  position: absolute;
  top: 50%;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-top: -22px;
  padding: 0;
  border: 1px solid rgb(255 255 255 / .28);
  border-radius: 50%;
  background: rgb(255 255 255 / .12);
  color: #fff;
  cursor: pointer;
  /* Sits behind the copy in stacking terms but in front of the artwork, and it
     is translucent, so a long headline is never hidden by it. */
  backdrop-filter: blur(6px);
  transition: background-color .2s ease, border-color .2s ease, transform .2s ease, opacity .2s ease;
  opacity: .75;
}

.hero__arrow:hover {
  opacity: 1;
  background: rgb(255 255 255 / .26);
  border-color: rgb(255 255 255 / .6);
}

.hero__arrow:focus-visible {
  opacity: 1;
  outline: 2px solid #fff;
  outline-offset: 3px;
}

.hero__arrow .icon { width: 1.3rem; height: 1.3rem; }

.hero__arrow--prev { left: clamp(.5rem, 2vw, 1.5rem); }
.hero__arrow--next { right: clamp(.5rem, 2vw, 1.5rem); }

.hero__arrow--prev:hover { transform: translateX(-2px); }
.hero__arrow--next:hover { transform: translateX(2px); }

/* On a phone the arrows would sit on top of the headline, and a swipe is the
   natural gesture there anyway — app.js binds one. */
@media (max-width: 48rem) {
  .hero__arrow { display: none; }
}

/* A slide on the light theme needs dark controls, or they vanish. */
.hero__slide--light ~ .hero__arrow,
.hero__slide--light ~ .hero__nav .hero__dot { background: rgb(15 23 42 / .18); }

/* ------------------------------------------------- hero: the per-slide art */

/* The illustrations are drawn for a tinted panel, not for the hero's dark
   ground, so on the brand and dark slides they are lightened as a whole rather
   than recoloured piece by piece. */
.hero__art-piece {
  width: min(100%, 360px);
  height: auto;
}

.hero__slide--brand .hero__art-piece,
.hero__slide--dark .hero__art-piece {
  --brand-050: rgb(255 255 255 / .10);
  --brand-100: rgb(255 255 255 / .18);
  --brand-600: rgb(255 255 255 / .85);
  --art-accent: #50e6ff;
  --paper-dark: #0d1117;
}

@media (prefers-reduced-motion: reduce) {
  /* The fill is a countdown, and with autoplay off there is nothing to count
     down. app.js already disables autoplay here; this stops any residual
     animation. */
  .hero__dot-fill { animation: none !important; }
  .hero__dot,
  .hero__arrow { transition: none; }
}

/* ---------------------------------------------------------------- domain search */

.domain-search { background: var(--paper-alt); }
.domain-search__form { display: flex; flex-wrap: wrap; gap: .6rem; max-width: 46rem; margin-inline: auto; }
.domain-search__input {
  flex: 1 1 16rem; min-width: 0; padding: .95rem 1.1rem;
  border: 1px solid var(--field-line); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink-900); font: inherit;
}
.domain-search__input:focus-visible { border-color: var(--brand-500); }

.domain-search__tlds { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin-top: 1.25rem; list-style: none; padding: 0; }
.domain-search__tlds li { margin: 0; }
.tld-chip {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .4rem .85rem; border-radius: var(--radius-pill);
  background: var(--paper); border: 1px solid var(--line);
  font-size: var(--step--1); font-weight: 700; color: var(--ink-900);
}
.tld-chip small { font-weight: 500; color: var(--ink-500); }

.domain-results { margin-top: 1.5rem; }
.domain-result {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: .75rem; padding: 1rem 1.25rem; margin-bottom: .6rem;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
}
.domain-result__name { font-weight: 700; color: var(--ink-900); }
.domain-result--available { border-left: 4px solid var(--accent-500); }
.domain-result--taken { border-left: 4px solid var(--danger-500); }
.domain-result--unknown { border-left: 4px solid var(--ink-300); }
.domain-result__state { font-size: var(--step--1); font-weight: 700; }
.domain-result--available .domain-result__state { color: var(--accent-700); }
.domain-result--taken .domain-result__state { color: var(--danger-500); }

/* ---------------------------------------------------------------- plans */

.plans { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); align-items: start; }

.plan {
  position: relative; display: flex; flex-direction: column;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-1);
  padding: clamp(22px, 3vw, 32px);
  transition: transform .15s ease, box-shadow .15s ease;
}
.plan:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }

.plan--featured { border-color: var(--brand-500); box-shadow: var(--shadow-3); }
@media (min-width: 992px) { .plan--featured { transform: scale(1.03); } .plan--featured:hover { transform: scale(1.03) translateY(-3px); } }

.plan__badge {
  position: absolute; top: -.8rem; left: 50%; transform: translateX(-50%);
  white-space: nowrap;
}

.plan__name { font-size: var(--step-1); margin-bottom: .15rem; }
.plan__tagline { font-size: var(--step--1); color: var(--ink-500); min-height: 2.6em; margin-bottom: 1rem; }

.plan__price { display: flex; align-items: baseline; flex-wrap: wrap; gap: .3rem; margin-bottom: .15rem; }
.plan__price-amount { font-size: var(--step-3); font-weight: 800; color: var(--ink-900); letter-spacing: -.03em; }
.plan__period { color: var(--ink-500); font-weight: 600; }
.plan__price-was { color: var(--ink-500); text-decoration: line-through; font-size: var(--step--1); }
.plan__save { font-size: var(--step--1); font-weight: 700; color: var(--accent-700); margin-bottom: 1.25rem; }

.plan__features { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: .55rem; }
.plan__features li { display: flex; align-items: flex-start; gap: .55rem; margin: 0; font-size: .95rem; }
.plan__features svg { width: 1.1em; height: 1.1em; margin-top: .3em; }
.plan__features .is-yes svg { color: var(--accent-500); }
.plan__features .is-no  { color: var(--ink-500); }
.plan__features .is-no svg { color: var(--ink-300); }

.plan__cta { margin-top: auto; }

.plan__review {
  margin-top: .75rem; padding: .5rem .7rem; border-radius: var(--radius-sm);
  background: var(--warn-050); color: #92400e; font-size: var(--step--1); font-weight: 600;
}

/* ---------------------------------------------------------------- matrix */

.matrix__wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); }
.matrix { width: 100%; min-width: 44rem; border-collapse: collapse; font-size: .95rem; }
.matrix th, .matrix td { padding: .85rem 1rem; text-align: center; border-bottom: 1px solid var(--line); }
.matrix thead th { position: sticky; top: 0; background: var(--paper-alt); font-size: var(--step--1); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-500); z-index: 1; }
.matrix tbody th { text-align: left; font-weight: 600; color: var(--ink-900); }
.matrix tbody tr:nth-child(even) { background: color-mix(in srgb, var(--paper-alt) 55%, transparent); }
.matrix tbody tr:last-child th, .matrix tbody tr:last-child td { border-bottom: 0; }
.matrix__yes svg { width: 1.15em; height: 1.15em; color: var(--accent-500); }
.matrix__no  svg { width: 1.15em; height: 1.15em; color: var(--ink-300); }
.matrix__val { font-weight: 600; color: var(--ink-900); }
.matrix__price { font-size: var(--step-1); font-weight: 800; color: var(--ink-900); }
.matrix col.is-featured { background: var(--brand-050); }

/* ---------------------------------------------------------------- includes strip */

.includes { display: grid; gap: 1px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.includes__item { display: flex; flex-direction: column; align-items: center; gap: .35rem; padding: 1.25rem .75rem; background: var(--paper); text-align: center; }
.includes__item svg { width: 22px; height: 22px; color: var(--brand-500); }
.includes__item strong { color: var(--ink-900); font-size: .95rem; }
.includes__item span { font-size: var(--step--1); color: var(--ink-500); }

/* ---------------------------------------------------------------- features grid */

.features { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
.feature { padding: clamp(20px, 2.5vw, 28px); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); }
.feature__icon { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 12px; background: var(--brand-050); color: var(--brand-on-tint); margin-bottom: .9rem; }
.feature__icon svg { width: 22px; height: 22px; }
.feature h3 { font-size: 1.1rem; margin-bottom: .35rem; }
.feature p { font-size: .95rem; color: var(--ink-500); margin: 0; }

/* ---------------------------------------------------------------- promo panels */

.promo { display: grid; gap: clamp(24px, 4vw, 56px); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .promo { grid-template-columns: 1fr 1fr; } }
.promo--reverse .promo__media { order: -1; }
@media (max-width: 899px) { .promo--reverse .promo__media { order: 0; } }

.promo__list { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: .6rem; }
.promo__list li { display: flex; align-items: flex-start; gap: .6rem; margin: 0; }
.promo__list svg { width: 1.2em; height: 1.2em; margin-top: .25em; color: var(--accent-500); }
.promo__price { font-size: var(--step-1); font-weight: 700; color: var(--ink-900); margin-bottom: 1.25rem; }

.promo__media { display: grid; place-items: center; min-height: 14rem; border-radius: var(--radius-lg); background: linear-gradient(135deg, var(--brand-050), var(--paper-alt)); border: 1px solid var(--line); }
.promo__media svg { width: 45%; max-width: 200px; height: auto; color: var(--brand-500); }

/* ---------------------------------------------------------------- tabs */

.tabs__nav { display: flex; flex-wrap: wrap; gap: .4rem; justify-content: center; margin-bottom: 1.75rem; padding: .35rem; background: var(--paper-alt); border: 1px solid var(--line); border-radius: var(--radius-pill); width: fit-content; margin-inline: auto; }
.tabs__btn {
  padding: .6rem 1.15rem; border: 0; border-radius: var(--radius-pill);
  background: none; color: var(--ink-500); font: inherit; font-weight: 600; cursor: pointer;
}
.tabs__btn[aria-selected="true"] { background: var(--paper); color: var(--brand-text); box-shadow: var(--shadow-1); }
.tabs__panel { max-width: 48rem; margin-inline: auto; text-align: center; }
.tabs__panel[hidden] { display: none; }
.tabs__lead { font-size: var(--step-1); font-weight: 600; color: var(--ink-900); margin-bottom: .75rem; }

/* ---------------------------------------------------------------- service cards */

/* 14.5rem rather than 17rem: this band carries four services now, and at 17rem
   the fourth wrapped to a row of its own on a 1280px screen. auto-fit still
   lets a three-item band spread to fill the row. */
.svc-cards { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14.5rem), 1fr)); }
.svc-card { position: relative; display: flex; flex-direction: column; gap: .5rem; padding: clamp(24px, 3vw, 34px); border-radius: var(--radius-lg); background: linear-gradient(160deg, var(--brand-700), var(--brand-500)); color: #fff; overflow: hidden; }
.svc-card__icon { position: absolute; right: -12px; bottom: -12px; opacity: .18; }
.svc-card__icon svg { width: 110px; height: 110px; }
.svc-card__kicker { font-size: var(--step--1); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #fff; opacity: .92; }
.svc-card h3 { color: #fff; font-size: var(--step-2); margin: 0 0 .75rem; }
.svc-card .btn { align-self: flex-start; margin-top: auto; position: relative; }

/* ---------------------------------------------------------------- strip */

.strip { background: linear-gradient(90deg, var(--brand-700), var(--brand-500)); color: #fff; text-align: center; }
.strip .container { padding-block: clamp(22px, 3vw, 34px); }
.strip h2 { color: #fff; font-size: var(--step-2); margin: 0; }

/* ---------------------------------------------------------------- testimonials */

.testimonials { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); }
.quote { display: flex; flex-direction: column; gap: 1rem; padding: clamp(22px, 3vw, 30px); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-1); }
.quote__stars { display: flex; gap: .1rem; color: var(--warn-500); }
.quote__stars svg { width: 1.05em; height: 1.05em; }
.quote__body { margin: 0; color: var(--ink-700); }
.quote__who { display: flex; align-items: center; gap: .75rem; margin-top: auto; }
.quote__avatar { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%; background: var(--brand-050); color: var(--brand-on-tint); font-weight: 700; flex: none; }
.quote__avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.quote__name { font-weight: 700; color: var(--ink-900); display: block; line-height: 1.3; }
.quote__meta { font-size: var(--step--1); color: var(--ink-500); }

/* ---------------------------------------------------------------- accordion */

.accordion { max-width: 52rem; margin-inline: auto; display: grid; gap: .6rem; }
.accordion__item { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.accordion__item[open] { border-color: var(--brand-500); }
.accordion__btn {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; padding: 1.05rem 1.25rem; cursor: pointer;
  font-weight: 600; color: var(--ink-900); list-style: none;
}
.accordion__btn::-webkit-details-marker { display: none; }
.accordion__btn:hover { background: var(--paper-alt); }
.accordion__btn svg { width: 1.1em; height: 1.1em; flex: none; color: var(--brand-text); transition: transform .18s ease; }
.accordion__item[open] .accordion__btn svg { transform: rotate(45deg); }
.accordion__panel { padding: 0 1.25rem 1.25rem; color: var(--ink-700); }
.accordion__panel > :last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- posts */

.posts { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); }
.post-card { display: flex; flex-direction: column; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-1); transition: transform .15s ease, box-shadow .15s ease; }
.post-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-3); }
.post-card__media { aspect-ratio: 16 / 9; background: linear-gradient(135deg, var(--brand-050), var(--paper-alt)); display: grid; place-items: center; }
.post-card__media img { width: 100%; height: 100%; object-fit: cover; }
.post-card__media svg { width: 42px; height: 42px; color: var(--brand-500); opacity: .6; }
.post-card__body { padding: 1.25rem; display: flex; flex-direction: column; gap: .5rem; flex: 1; }
.post-card__meta { display: flex; flex-wrap: wrap; gap: .5rem 1rem; font-size: var(--step--1); color: var(--ink-500); }
.post-card h3 { font-size: 1.15rem; margin: 0; }
.post-card h3 a { color: var(--ink-900); }
.post-card h3 a:hover { color: var(--brand-text); text-decoration: none; }
.post-card p { font-size: .95rem; color: var(--ink-500); margin: 0; }
.post-card__more { margin-top: auto; }

/* ---------------------------------------------------------------- prose */

.prose { max-width: 46rem; }
.prose > :first-child { margin-top: 0; }
.prose h2 { font-size: var(--step-2); margin-top: 2rem; }
.prose h3 { font-size: var(--step-1); margin-top: 1.75rem; }
.prose ul, .prose ol { padding-left: 1.4em; }
.prose li { margin-bottom: .35em; }
.prose blockquote { margin: 1.5rem 0; padding: .75rem 1.25rem; border-left: 3px solid var(--brand-500); background: var(--paper-alt); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--ink-700); }
.prose code { font-family: var(--mono); font-size: .9em; padding: .15em .4em; border-radius: 4px; background: var(--paper-alt); border: 1px solid var(--line); }
.prose pre { overflow-x: auto; padding: 1rem; border-radius: var(--radius-sm); background: var(--ink-900); color: #e2e8f0; }
.prose pre code { background: none; border: 0; color: inherit; }
.prose img { border-radius: var(--radius); margin: 1.5rem 0; }
.prose table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; }
.prose th, .prose td { padding: .6rem .8rem; border: 1px solid var(--line); text-align: left; }
.prose thead th { background: var(--paper-alt); }
.prose .lede { color: var(--ink-500); }

/* ---------------------------------------------------------------- page hero */

.page-hero { background: var(--paper-alt); border-bottom: 1px solid var(--line); padding: clamp(36px, 5vw, 64px) 0; }

/* .page-head is the sibling that site/pricing.php uses. It had no base rule
   at all, so the band was a zero-height box: the heading collided with the
   header and the texture had nothing to paint into. Same treatment as
   .page-hero, so the two never look like different sites. */
.page-head { background: var(--paper-alt); border-bottom: 1px solid var(--line); padding: clamp(36px, 5vw, 64px) 0; }
.page-head__kicker {
  margin: 0 0 .35rem;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--brand-text);
}
.page-head__title { margin: 0 0 .35rem; }
.page-head__sub { margin: 0; max-width: 46rem; color: var(--ink-500); font-size: var(--step-1); }
.page-hero h1 { margin-bottom: .35rem; }
.page-hero p { color: var(--ink-500); font-size: var(--step-1); margin: 0; max-width: 46rem; }

/* ---------------------------------------------------------------- forms */

.form { display: grid; gap: 1.1rem; }
.form__row { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.field { display: grid; gap: .35rem; }
.field__label { font-weight: 600; font-size: .95rem; color: var(--ink-900); }
.field__label .req { color: var(--danger-500); }
.field__input,
.field select,
.field textarea {
  width: 100%; padding: .75rem .9rem; font: inherit; color: var(--ink-900);
  background: var(--paper); border: 1px solid var(--field-line); border-radius: var(--radius-sm);
}
.field textarea { min-height: 9rem; resize: vertical; }
.field__input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { border-color: var(--brand-500); }
.field__hint { font-size: var(--step--1); color: var(--ink-500); }
.field__error { font-size: var(--step--1); font-weight: 600; color: var(--danger-500); }
.field.has-error .field__input, .field.has-error select, .field.has-error textarea { border-color: var(--danger-500); }
.field--check { grid-template-columns: auto 1fr; align-items: start; gap: .6rem; }
.field--check input { margin-top: .3em; }
.form__actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }

/* ---------------------------------------------------------------- alerts */

.flash-stack { display: grid; gap: .6rem; padding-top: 1.25rem; }
.alert { display: flex; align-items: flex-start; gap: .7rem; padding: .9rem 1.1rem; border-radius: var(--radius-sm); border: 1px solid transparent; font-weight: 500; }
.alert p { margin: 0; flex: 1; }
.alert__icon { width: 1.2em; height: 1.2em; margin-top: .2em; flex: none; }
.alert__close { border: 0; background: none; font-size: 1.4rem; line-height: 1; cursor: pointer; color: inherit; opacity: .55; padding: 0 .1em; }
.alert__close:hover { opacity: 1; }
.alert--success { background: var(--accent-050); border-color: color-mix(in srgb, var(--accent-500) 35%, transparent); color: #065f46; }
.alert--error   { background: var(--danger-050); border-color: color-mix(in srgb, var(--danger-500) 35%, transparent); color: #991b1b; }
.alert--warning { background: var(--warn-050); border-color: color-mix(in srgb, var(--warn-500) 35%, transparent); color: #92400e; }
.alert--info    { background: var(--brand-050); border-color: color-mix(in srgb, var(--brand-500) 30%, transparent); color: var(--brand-on-tint); }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .alert--success { color: #6ee7b7; }
  :root:not([data-theme="light"]) .alert--error   { color: #fca5a5; }
  :root:not([data-theme="light"]) .alert--warning { color: #fcd34d; }
  :root:not([data-theme="light"]) .alert--info    { color: #93b4fd; }
}

:root[data-theme="dark"] .alert--success { color: #6ee7b7; }
:root[data-theme="dark"] .alert--error   { color: #fca5a5; }
:root[data-theme="dark"] .alert--warning { color: #fcd34d; }
:root[data-theme="dark"] .alert--info    { color: #93b4fd; }

/* ---------------------------------------------------------------- misc */

.breadcrumb { border-bottom: 1px solid var(--line); background: var(--paper); font-size: var(--step--1); }
.breadcrumb ol { display: flex; flex-wrap: wrap; gap: .35rem; list-style: none; margin: 0; padding: .75rem 0; }
.breadcrumb li { margin: 0; color: var(--ink-500); }
.breadcrumb li + li::before { content: "/"; margin-right: .35rem; color: var(--ink-300); }

.pagination { display: flex; flex-wrap: wrap; justify-content: center; gap: .35rem; margin-top: 2.5rem; }
.pagination__link { display: grid; place-items: center; min-width: 2.5rem; height: 2.5rem; padding: 0 .6rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font-weight: 600; color: var(--ink-700); }
.pagination__link:hover { background: var(--brand-050); border-color: var(--brand-500); text-decoration: none; }
.pagination__link.is-active { background: var(--brand-600); border-color: var(--brand-text); color: #fff; }
.pagination__link svg { width: 1.1em; height: 1.1em; }
.pagination__gap { display: grid; place-items: center; min-width: 2rem; height: 2.5rem; color: var(--ink-500); }

.table { width: 100%; border-collapse: collapse; }
.table th, .table td { padding: .8rem 1rem; text-align: left; border-bottom: 1px solid var(--line); }
.table thead th { font-size: var(--step--1); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-500); background: var(--paper-alt); }
.table tbody tr:hover { background: var(--paper-alt); }
.table--wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }

.empty-state { text-align: center; padding: clamp(32px, 6vw, 64px) 1.5rem; color: var(--ink-500); }
.empty-state svg { width: 46px; height: 46px; color: var(--ink-300); margin: 0 auto 1rem; }
.empty-state h2 { font-size: var(--step-1); }

.stat { text-align: center; }
.stat__num { display: block; font-size: var(--step-3); font-weight: 800; color: var(--brand-text); letter-spacing: -.03em; line-height: 1.1; }
.stat__label { font-size: var(--step--1); color: var(--ink-500); text-transform: uppercase; letter-spacing: .07em; font-weight: 600; }

.cta-band { background: linear-gradient(135deg, var(--brand-700), var(--brand-500)); color: #fff; text-align: center; border-radius: var(--radius-lg); padding: clamp(32px, 5vw, 56px) clamp(20px, 4vw, 48px); }
.cta-band h2 { color: #fff; }
.cta-band p { color: #fff; max-width: 38rem; margin-inline: auto; }
.cta-band .form__actions { justify-content: center; margin-top: 1.5rem; }

.socials { display: flex; flex-wrap: wrap; gap: .5rem; list-style: none; margin: 1.25rem 0 0; padding: 0; }
.socials li { margin: 0; }
.socials a { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 10px; background: rgb(255 255 255 / .08); color: #cbd5e1; }
.socials a:hover { background: var(--brand-600); color: #fff; }
.socials svg { width: 18px; height: 18px; }

/* ---------------------------------------------------------------- footer */

.site-footer { background: var(--paper-dark); color: var(--on-dark-700); margin-top: auto; }
.site-footer a { color: #cbd5e1; }
.site-footer a:hover { color: #fff; }

.site-footer__help { border-bottom: 1px solid rgb(255 255 255 / .08); }
.site-footer__help-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.25rem; padding-block: 1.5rem; }
.site-footer__help-text { display: flex; align-items: center; gap: .6rem; margin: 0; color: #cbd5e1; }
.site-footer__help-text svg { width: 1.4em; height: 1.4em; color: var(--brand-500); }
.site-footer__help-text strong { color: #fff; }

.newsletter { display: flex; flex-wrap: wrap; gap: .5rem; flex: 1 1 22rem; max-width: 32rem; }
.newsletter__input { flex: 1 1 12rem; min-width: 0; padding: .7rem 1rem; border: 1px solid rgb(255 255 255 / .16); border-radius: var(--radius-sm); background: rgb(255 255 255 / .06); color: #fff; font: inherit; }
.newsletter__input::placeholder { color: #94a3b8; }

.site-footer__main { padding-block: clamp(36px, 5vw, 56px); }
.site-footer__cols { display: grid; gap: clamp(24px, 3vw, 40px); grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.site-footer__col--brand { grid-column: span 1; }
@media (min-width: 992px) { .site-footer__col--brand { grid-column: span 2; max-width: 22rem; } }

.site-footer__heading { font-size: .95rem; text-transform: uppercase; letter-spacing: .08em; color: #fff; margin-bottom: 1rem; }
.site-footer__links { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.site-footer__links li { margin: 0; }
.site-footer__links a { font-size: .95rem; }

.footer-contact { font-style: normal; margin-top: 1.25rem; display: grid; gap: .6rem; }
.footer-contact p { display: flex; align-items: flex-start; gap: .6rem; margin: 0; font-size: .95rem; }
.footer-contact svg { width: 1.15em; height: 1.15em; margin-top: .25em; color: var(--brand-500); flex: none; }

.site-footer__bottom { border-top: 1px solid rgb(255 255 255 / .08); }
.site-footer__bottom-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .75rem; padding-block: 1.25rem; font-size: var(--step--1); }
.site-footer__copy { margin: 0; }
.site-footer__legal { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; list-style: none; margin: 0; padding: 0; }
.site-footer__legal li { margin: 0; }

/* Sticky footer without a wrapper element. */
body.site { display: flex; flex-direction: column; min-height: 100vh; }
body.site > main { flex: 1; }

/* ---------------------------------------------------------------- print */

@media print {
  .site-header, .site-footer, .promo-bar, .breadcrumb, .pagination, .nav, .btn { display: none !important; }
  body { color: #000; background: #fff; }
  .container { max-width: none; }
}

/* ---------------------------------------------------------------- customer area */

.client-nav { display: flex; flex-wrap: wrap; gap: .25rem; list-style: none; margin: 0; padding: .5rem 0; }
.client-nav li { margin: 0; }
.client-nav__link {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .45rem .8rem; border-radius: var(--radius-pill);
  font-size: .92rem; font-weight: 600; color: var(--ink-500);
}
.client-nav__link:hover { background: var(--brand-050); color: var(--brand-on-tint); text-decoration: none; }
.client-nav__link.is-active { background: var(--brand-600); color: #fff; }
.client-nav__link svg { width: 1em; height: 1em; }
.client-nav__link .badge { font-size: .68rem; }

.auth-narrow { max-width: 30rem; margin-inline: auto; }
.auth-narrow--wide { max-width: 46rem; }

.dl { display: grid; gap: .5rem .9rem; grid-template-columns: auto 1fr; margin: 0; font-size: .95rem; }
.dl dt { color: var(--ink-500); }
.dl dd { margin: 0; color: var(--ink-900); font-weight: 600; }

.inv { max-width: 52rem; margin-inline: auto; }
.inv__head { display: flex; flex-wrap: wrap; gap: 1.5rem; justify-content: space-between; margin-bottom: 2rem; }
.inv__total { text-align: right; font-size: var(--step-2); font-weight: 800; color: var(--ink-900); }
.inv table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }
.inv th, .inv td { padding: .7rem .5rem; border-bottom: 1px solid var(--line); text-align: left; }
.inv td.num, .inv th.num { text-align: right; font-variant-numeric: tabular-nums; }
.inv tfoot td { border-bottom: 0; font-weight: 600; }

.bank-box { background: var(--paper-alt); border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem 1.15rem; }
.bank-box pre { margin: 0; font-family: var(--mono); font-size: .88rem; white-space: pre-wrap; color: var(--ink-900); }

@media print {
  .client-nav, .page-hero form { display: none !important; }
  .inv { max-width: none; }
}

/* ------------------------------------------------- light / dark toggle */

/* Ships with the `hidden` attribute and is revealed by theme.js, so it never
   sits in the header doing nothing when JavaScript is off. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.theme-toggle[hidden] { display: none; }

.theme-toggle:hover {
  background: rgb(255 255 255 / .12);
  border-color: rgb(255 255 255 / .2);
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--tech-400);
  outline-offset: 2px;
}

.theme-toggle .icon { width: 1rem; height: 1rem; }

/* One icon at a time: sun while light (press it for dark), moon while dark. */
.theme-toggle__icon { display: none; line-height: 0; }
.theme-toggle[aria-pressed="false"] .theme-toggle__icon--sun  { display: inline-block; }
.theme-toggle[aria-pressed="true"]  .theme-toggle__icon--moon { display: inline-block; }

@media (prefers-reduced-motion: reduce) {
  .theme-toggle { transition: none; }
}

/* -------------------------------------------------- credibility strip */

.trust-strip {
  border-block: 1px solid var(--line);
  background: var(--paper-alt);
  padding: 1.1rem 0;
}

.trust-strip__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem 1.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.trust-strip__item {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 0;
}

/* Separators between columns, but never a trailing one and never on the
   wrapped rows where they would float mid-air. */
@media (min-width: 60rem) {
  .trust-strip__item + .trust-strip__item { border-left: 1px solid var(--line); padding-left: 1.75rem; }
}

.trust-strip__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 10px;
  background: var(--brand-050);
  color: var(--brand-on-tint);
}

.trust-strip__icon .icon { width: 1.15rem; height: 1.15rem; }

.trust-strip__text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }

.trust-strip__figure {
  font-size: var(--step-1);
  font-weight: 750;
  letter-spacing: -.01em;
  color: var(--ink-900);
}

.trust-strip__label { font-size: var(--step--1); color: var(--ink-500); }

/* ------------------------------------------- hero illustration sizing */

.hero__art {
  width: 100%;
  max-width: 32rem;
  height: auto;
  /* The art is drawn on the hero's own dark gradient, so it needs no theming:
     every fill is white-with-opacity or the cyan accent. */
}

@media (max-width: 60rem) {
  .hero__art { max-width: 22rem; margin-inline: auto; }
}

/* ------------------------------------------------- footer strapline */

.footer-strap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .35rem .6rem;
  margin: .85rem 0 .35rem;
}

.footer-strap__tag {
  font-size: var(--step--1);
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tech-300);
}

.footer-strap__since { font-size: var(--step--1); color: #a8b0be; }

.footer-services {
  margin: 0 0 1rem;
  font-size: var(--step--1);
  line-height: 1.55;
  color: #8f97a5;
  max-width: 22rem;
}

/* ---------------------------------------------------------- brand logo */

/* An inline <svg> has no intrinsic size once it only carries a viewBox, so it
   collapses to 0x0 without this. Height is fixed and width follows the 5:1
   aspect ratio of the artwork. */
.brand-logo {
  display: block;
  height: 2.25rem;
  width: auto;
  /* Tied to the viewBox in partials/site/brand-logo.php, which is cropped to
     the artwork (0 0 181 40). Change one and you must change the other. */
  aspect-ratio: 181 / 40;
  flex: none;
  /* The wordmark is currentColor, so it follows the surrounding text and needs
     no separate light-background and dark-background asset. */
  color: var(--ink-900);
}

.site-header .brand-logo { height: 2.35rem; }

/* The footer sits on a permanently dark panel whatever the theme. */
.site-footer .brand-logo { color: #ffffff; height: 2.4rem; }

@media (max-width: 40rem) {
  .brand-logo { height: 1.95rem; }
  .site-header .brand-logo { height: 2rem; }
}

/* The mark-only variant is square-ish, not 5:1. */
.brand-logo--mark { aspect-ratio: 54 / 40; }

/* ----------------------------------------------------- top-bar region chip */

/* Which region the visitor is served from and priced in. A statement, not a
   control: there is one price list and one set of datacentres, so it is marked
   up as a span rather than a button — nothing here is clickable, and making it
   look clickable would promise a choice that does not exist. */
.topbar-region {
  display: inline-flex;
  align-items: center;
}

.topbar-region__chip {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .2rem .5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill, 999px);
  background: var(--paper);
  line-height: 1.3;
  white-space: nowrap;
}

.topbar-region__chip .icon {
  width: .95rem;
  height: .95rem;
  color: var(--brand-text);
  flex: none;
}

.topbar-region__name { font-weight: 600; }

/* The detail line is separated by a rule rather than punctuation, so it still
   reads as secondary when the strings are translated or lengthened. */
.topbar-region__note {
  padding-left: .45rem;
  margin-left: .1rem;
  border-left: 1px solid var(--line);
  color: var(--ink-500);
}

/* --------------------------------------------------- reading progress bar */

/* How far down the page the reader is. z-index 105 puts it above the sticky
   header (100) but below the mobile drawer and its scrim (110/120), so an open
   drawer covers it rather than having a stray line float over the overlay.
   pointer-events: none because it sits across the top of the header and must
   never intercept a click meant for the logo. */
.reading-progress {
  position: fixed;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 105;
  pointer-events: none;
  background: transparent;
  /* Hidden until the JS finds the page is long enough to be worth a bar. */
  opacity: 0;
  transition: opacity .2s ease;
}

.reading-progress.is-visible { opacity: 1; }

.reading-progress--top    { top: 0; }
.reading-progress--bottom { bottom: 0; }

/* Scaled rather than width-animated: transform is compositor-only, so this
   costs nothing on the scroll path. transform-origin pins the growth to the
   left edge, and in a right-to-left document to the right one. */
.reading-progress__fill {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand-700), var(--brand-500));
  transition: transform .08s linear;
}

[dir="rtl"] .reading-progress__fill { transform-origin: 100% 50%; }

@media (prefers-reduced-motion: reduce) {
  /* The bar still tracks the scroll — it is information, not decoration — but
     it stops easing towards each new value. */
  .reading-progress__fill { transition: none; }
  .reading-progress { transition: none; }
}
/* ------------------------------------------- top-bar social + nav utilities */

/* The gap was .15rem — 2.4px between 28px round targets, so the icons read as
   one crowded clump rather than five separate links. .4rem gives each its own
   space without the row falling apart, and the margin-left separates the group
   from the region chip beside it. */
.topbar-social {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin-left: .25rem;
}

.topbar-social__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  color: inherit;
  opacity: .8;
  transition: opacity .15s ease, background-color .15s ease;
}

.topbar-social__link:hover,
.topbar-social__link:focus-visible { opacity: 1; background: rgb(255 255 255 / .12); }

.topbar-social__link .icon { width: .95rem; height: .95rem; }

/* Help and Cart, sitting either side of sign-in. */
.nav__util {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .4rem .55rem;
  border-radius: var(--radius-sm, 8px);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-700);
  white-space: nowrap;
  transition: background-color .15s ease, color .15s ease;
}

.nav__util:hover,
.nav__util:focus-visible { background: var(--brand-050); color: var(--brand-on-tint); }

.nav__util .icon { width: 1.05rem; height: 1.05rem; }

/* The count sits on the cart, and is decorative: the accessible name on the
   link already says how many items are in the basket. */
.nav__badge {
  position: absolute;
  top: -.15rem;
  right: -.15rem;
  min-width: 1.15rem;
  height: 1.15rem;
  padding: 0 .25rem;
  border-radius: 999px;
  background: var(--brand-600);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  line-height: 1.15rem;
  text-align: center;
}

/* On narrow screens the word goes and the icon stays. */
@media (max-width: 62rem) {
  .nav__util-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .nav__util { padding: .4rem; }
}

@media (prefers-reduced-motion: reduce) {
  .topbar-social__link, .nav__util { transition: none; }
}

/* --------------------------------------------------------------- basket */

.plan-card__add { margin: 0; }

.plan-card__add .icon { width: 1rem; height: 1rem; margin-right: .4rem; }

.plan-card__direct {
  display: block;
  margin-top: .5rem;
  font-size: var(--step--1);
  text-align: center;
  color: var(--ink-500);
}

.cart {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 62rem) {
  .cart { grid-template-columns: minmax(0, 1fr) 20rem; }
}

.cart-table { width: 100%; border-collapse: collapse; font-size: var(--step--1); }

.cart-table th, .cart-table td {
  padding: .8rem .6rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: middle;
}

.cart-table thead th {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-500);
  border-bottom-width: 2px;
}

.cart-table .num { text-align: right; }
.cart-table__plan a { font-weight: 650; }
.cart-table__domain,
.cart-table__setup { display: block; font-size: .78rem; color: var(--ink-500); }
.cart-table__total { font-weight: 700; white-space: nowrap; }

.cart-qty { display: inline-flex; gap: .35rem; align-items: center; margin: 0; }
.cart-qty__input {
  width: 3.4rem;
  padding: .3rem .4rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink-900);
  text-align: center;
}

.cart-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: none;
  color: var(--ink-500);
  cursor: pointer;
}

.cart-remove:hover { border-color: var(--danger-500); color: var(--danger-500); }
.cart-remove .icon { width: .95rem; height: .95rem; }

.cart__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  margin-top: 1.1rem;
}

.cart__actions form { margin: 0; }

.cart__summary {
  padding: 1.35rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper-alt);
  position: sticky;
  top: 1rem;
}

.cart-summary__list { margin: 1rem 0; }
.cart-summary__list > div { display: flex; justify-content: space-between; gap: 1rem; padding: .35rem 0; }
.cart-summary__list dt { color: var(--ink-700); margin: 0; }
.cart-summary__list dd { margin: 0; font-weight: 600; }

.cart-summary__total {
  border-top: 1px solid var(--line);
  margin-top: .5rem;
  padding-top: .7rem !important;
  font-size: var(--step-1);
}

.cart-summary__total dd { font-weight: 750; }

.cart-summary__pay,
.cart-summary__note {
  display: flex;
  gap: .5rem;
  margin: .9rem 0 0;
  font-size: .82rem;
  line-height: 1.5;
  color: var(--ink-500);
}

.cart-summary__pay .icon { flex: none; width: 1.05rem; height: 1.05rem; color: var(--accent-700); }

/* ------------------------------------------------------- empty states */

.empty-state {
  padding: clamp(2rem, 6vw, 3.5rem) 1.5rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper-alt);
  text-align: center;
}

.empty-state__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: .85rem;
  border-radius: 999px;
  background: var(--brand-050);
  color: var(--brand-on-tint);
}

.empty-state__icon .icon { width: 1.5rem; height: 1.5rem; }
.empty-state p { color: var(--ink-500); }
.empty-state__actions { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: center; margin-top: 1.1rem; }

/* ------------------------------------------------------------ captcha */

.captcha .captcha__input { max-width: 9rem; }

/* ------------------------------------------------- menu alignment (desktop) */

/* Above the drawer breakpoint the header bar becomes a three-track grid, and
   .nav is taken out of the box model with display:contents so the menu list and
   the Help/Sign in/Cart group become grid items in their own right. That is
   what allows the list to be genuinely centred rather than merely "centred in
   whatever space is left", which looks off when the logo and the buttons are
   different widths.

   .nav keeps its own box below 992px, where it is the slide-in drawer. */
@media (min-width: 992px) {
  .site-header__bar-inner {
    display: grid;
    align-items: center;
    gap: 1rem;
  }

  .site-header__bar-inner > .nav { display: contents; }

  /* Centred: equal side tracks, so the list sits on the page's centre line. */
  /* Fallback first, so the header still lays out in three columns if
     data-nav-align is ever missing from <html>. Without this the bar is
     display:grid with no tracks and no placement, auto-placement drops the
     logo, the menu and the buttons into one implicit column, and the whole
     header stacks vertically. The PHP validates the setting, but the CSS should
     not depend on that being the only way this attribute gets set. */
  .site-header__bar-inner { grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr); }
  .site-header__bar-inner > .logo { grid-column: 1; justify-self: start; }
  .site-header__bar-inner > .nav__list { grid-column: 2; justify-self: center; }
  .site-header__bar-inner > .nav__cta { grid-column: 3; justify-self: end; }

  [data-nav-align="center"] .site-header__bar-inner { grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr); }
  [data-nav-align="center"] .site-header__bar-inner > .logo { grid-column: 1; justify-self: start; }

  /* Belt and braces: whatever the track does, the brand does not shrink. */
  .site-header__bar-inner > .logo { min-width: max-content; }
  [data-nav-align="center"] .nav__list { grid-column: 2; justify-self: center; }
  [data-nav-align="center"] .nav__cta  { grid-column: 3; justify-self: end; }

  /* Next to the logo. */
  [data-nav-align="left"] .site-header__bar-inner { grid-template-columns: auto 1fr auto; }
  [data-nav-align="left"] .site-header__bar-inner > .logo { grid-column: 1; }
  [data-nav-align="left"] .nav__list { grid-column: 2; justify-self: start; }
  [data-nav-align="left"] .nav__cta  { grid-column: 3; justify-self: end; }

  /* Next to the buttons. */
  [data-nav-align="right"] .site-header__bar-inner { grid-template-columns: auto 1fr auto; }
  [data-nav-align="right"] .site-header__bar-inner > .logo { grid-column: 1; }
  [data-nav-align="right"] .nav__list { grid-column: 2; justify-self: end; }
  [data-nav-align="right"] .nav__cta  { grid-column: 3; justify-self: end; }

  /* A dropdown is positioned against its own item, which still has a box. */
  .nav__list { position: relative; }
}

/* ------------------------------------------------------------ pricing page */

.pricing-notes {
  display: flex;
  gap: .55rem;
  align-items: flex-start;
  margin: 0 0 1.75rem;
  padding: .8rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md, 10px);
  background: var(--paper-alt);
  font-size: var(--step--1);
  color: var(--ink-700);
}

.pricing-notes .icon { flex: none; width: 1.05rem; height: 1.05rem; color: var(--brand-text); margin-top: .1rem; }

/* Jump links. Sticky so they stay reachable down a long page. */
.pricing-jump {
  position: sticky;
  top: 0;
  z-index: 5;
  margin-bottom: 1.5rem;
  padding: .6rem 0;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}

.pricing-jump ul {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pricing-jump li { margin: 0; }

.pricing-jump a {
  display: inline-block;
  padding: .32rem .7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-700);
}

.pricing-jump a:hover,
.pricing-jump a:focus-visible {
  border-color: var(--brand-500);
  background: var(--brand-050);
  color: var(--brand-on-tint);
  text-decoration: none;
}

.pricing-group { margin-bottom: clamp(2rem, 5vw, 3.25rem); scroll-margin-top: 4.5rem; }

.pricing-group__head { margin-bottom: 1rem; }

.pricing-group__head h2 { display: flex; align-items: center; gap: .55rem; margin: 0 0 .2rem; }

.pricing-group__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 8px;
  background: var(--brand-050);
  color: var(--brand-on-tint);
}

.pricing-group__icon .icon { width: 1.05rem; height: 1.05rem; }
.pricing-group__sub { margin: 0 0 .35rem; color: var(--ink-500); font-size: var(--step--1); }

/* A wide table scrolls inside its own box; the page never scrolls sideways. */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  -webkit-overflow-scrolling: touch;
}

.pricing-table { width: 100%; min-width: 34rem; border-collapse: collapse; font-size: var(--step--1); }

.pricing-table th,
.pricing-table td {
  padding: .8rem .9rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: middle;
}

.pricing-table tbody tr:last-child th,
.pricing-table tbody tr:last-child td { border-bottom: 0; }

.pricing-table thead th {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-500);
  background: var(--paper-alt);
  border-bottom-width: 2px;
  white-space: nowrap;
}

.pricing-table .num { text-align: right; }

.pricing-table tbody tr.is-featured { background: var(--brand-050); }

.pricing-table__plan { min-width: 12rem; }
.pricing-table__name { display: block; font-weight: 700; color: var(--ink-900); }

.pricing-table__badge {
  display: inline-block;
  margin-top: .25rem;
  padding: .1rem .45rem;
  border-radius: 4px;
  background: var(--tech-600);
  color: #fff;
  font-size: .66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.pricing-table__tagline { display: block; margin-top: .2rem; color: var(--ink-500); font-size: .78rem; font-weight: 400; }
.pricing-table__price { font-weight: 700; color: var(--ink-900); white-space: nowrap; }
.pricing-table__was { display: block; font-size: .74rem; color: var(--ink-500); }
.pricing-table__none { color: var(--ink-500); }

.pricing-review {
  display: flex;
  gap: .5rem;
  align-items: flex-start;
  margin: .8rem 0 0;
  padding: .7rem .9rem;
  border: 1px dashed var(--warn-500);
  border-radius: 8px;
  background: var(--warn-050);
  font-size: var(--step--1);
  color: var(--ink-800);
}

.pricing-review .icon { flex: none; width: 1.05rem; height: 1.05rem; color: var(--warn-500); margin-top: .1rem; }

.pricing-cta {
  margin-top: clamp(1.5rem, 4vw, 2.5rem);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  border-radius: var(--radius-lg);
  background: var(--paper-alt);
  border: 1px solid var(--line);
  text-align: center;
}

.pricing-cta p { color: var(--ink-700); max-width: 44rem; margin-inline: auto; }
.pricing-cta__actions { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: center; margin-top: 1rem; }

@media (prefers-reduced-motion: reduce) {
  .pricing-group { scroll-behavior: auto; }
}

/* ------------------------------------------------------------ chat widget */

.chat {
  position: fixed;
  right: clamp(.75rem, 3vw, 1.5rem);
  bottom: clamp(.75rem, 3vw, 1.5rem);
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .6rem;
  font-size: var(--step--1);
  /* The container itself catches nothing. On a phone it is stretched to the
     full width (see the 26rem query below), so an invisible band across the
     bottom of the page was swallowing taps meant for the footer links behind
     it. The launcher and the panel take their own clicks back. */
  pointer-events: none;
}

.chat > * { pointer-events: auto; }

.chat[hidden] { display: none; }

/* -------------------------------------------------------------- launcher */

.chat__launcher {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .7rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: var(--brand-600);
  color: #fff;
  font-size: var(--step--1);
  font-weight: 650;
  cursor: pointer;
  box-shadow: var(--shadow-3);
  transition: background-color .15s ease;
}

.chat__launcher:hover { background: var(--brand-700); }
.chat__launcher:focus-visible { outline: 2px solid var(--tech-400); outline-offset: 3px; }
.chat__launcher .icon { width: 1.15rem; height: 1.15rem; }

.chat__unread {
  position: absolute;
  top: -.3rem;
  right: -.3rem;
  min-width: 1.3rem;
  height: 1.3rem;
  padding: 0 .3rem;
  border-radius: 999px;
  background: var(--danger-500);
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  line-height: 1.3rem;
  text-align: center;
}

.chat__unread[hidden] { display: none; }

/* ----------------------------------------------------------------- panel */

.chat__panel {
  display: flex;
  flex-direction: column;
  width: min(92vw, 22.5rem);
  max-height: min(80vh, 34rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}

.chat__panel[hidden] { display: none; }

.chat__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .75rem;
  padding: .9rem 1rem;
  background: linear-gradient(135deg, var(--brand-700), var(--brand-500));
  color: #fff;
}

.chat__title { margin: 0; font-size: 1rem; font-weight: 700; }
.chat__status { margin: .15rem 0 0; font-size: .78rem; opacity: .85; }

.chat__close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 0;
  border-radius: 999px;
  background: rgb(255 255 255 / .16);
  color: #fff;
  cursor: pointer;
}

.chat__close:hover { background: rgb(255 255 255 / .28); }
.chat__close .icon { width: 1rem; height: 1rem; }

.chat__body { flex: 1; overflow-y: auto; padding: 1rem; }
.chat__loading p, .chat__intro { margin: 0 0 .8rem; color: var(--ink-500); }

/* ----------------------------------------------------- pick a department */

.chat__departments { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.chat__departments li { margin: 0; }

.chat__dept {
  display: grid;
  gap: .15rem;
  width: 100%;
  padding: .75rem .85rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  text-align: left;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}

.chat__dept:hover { border-color: var(--brand-500); background: var(--brand-050); }
.chat__dept:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }

.chat__dept-name {
  display: flex;
  align-items: center;
  gap: .45rem;
  font-weight: 700;
  color: var(--ink-900);
}

.chat__dept-blurb { color: var(--ink-500); font-size: .8rem; }
.chat__dept-avail { color: var(--ink-500); font-size: .74rem; }

.chat__dot { width: .5rem; height: .5rem; border-radius: 999px; flex: none; }
.chat__dot.is-online { background: var(--accent-500); }
.chat__dot.is-away   { background: var(--ink-400); }

/* ------------------------------------------------------------- the form */

.chat__form-lead { margin: 0 0 .85rem; color: var(--ink-700); }
.chat__field { margin-bottom: .7rem; }

.chat__field label {
  display: block;
  margin-bottom: .2rem;
  font-size: .8rem;
  font-weight: 650;
  color: var(--ink-800);
}

.chat__field input,
.chat__field textarea {
  width: 100%;
  padding: .5rem .6rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  color: var(--ink-900);
  font: inherit;
}

.chat__field input:focus-visible,
.chat__field textarea:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }

.chat__hint { display: block; margin-top: .2rem; color: var(--ink-500); font-size: .74rem; }

.chat__error {
  margin: .5rem 0;
  padding: .5rem .65rem;
  border-radius: 8px;
  background: var(--danger-050);
  color: #991b1b;
  font-size: .8rem;
}

.chat__error[hidden] { display: none; }

.chat__back {
  display: block;
  width: 100%;
  margin-top: .6rem;
  padding: .4rem;
  border: 0;
  background: none;
  color: var(--ink-500);
  font-size: .8rem;
  cursor: pointer;
  text-decoration: underline;
}

/* -------------------------------------------------------- the transcript */

.chat__thread { overflow-y: auto; }
.chat__messages { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }

.chat__msg {
  display: grid;
  gap: .1rem;
  max-width: 85%;
  padding: .5rem .7rem;
  border-radius: 12px;
  margin: 0;
}

.chat__msg-who { font-size: .7rem; font-weight: 700; opacity: .75; }

/* pre-line keeps the typed line breaks; the text is inserted with
   textContent, so markup in a message is never interpreted. */
.chat__msg-body { white-space: pre-line; overflow-wrap: anywhere; }

.chat__msg--visitor {
  justify-self: end;
  background: var(--brand-600);
  color: #fff;
  border-bottom-right-radius: 4px;
}

.chat__msg--agent {
  justify-self: start;
  background: var(--paper-alt);
  border: 1px solid var(--line);
  color: var(--ink-900);
  border-bottom-left-radius: 4px;
}

.chat__msg--system {
  justify-self: stretch;
  max-width: 100%;
  background: var(--brand-050);
  color: var(--brand-on-tint);
  font-size: .8rem;
  text-align: center;
}

/* --------------------------------------------------------------- compose */

.chat__compose {
  display: flex;
  gap: .45rem;
  align-items: flex-end;
  padding: .7rem;
  border-top: 1px solid var(--line);
  background: var(--paper);
}

.chat__compose[hidden] { display: none; }

.chat__compose textarea {
  flex: 1;
  min-height: 2.4rem;
  max-height: 7rem;
  padding: .55rem .65rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink-900);
  font: inherit;
  resize: vertical;
}

.chat__send {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  border: 0;
  border-radius: 10px;
  background: var(--brand-600);
  color: #fff;
  cursor: pointer;
}

.chat__send:hover { background: var(--brand-700); }
.chat__send .icon { width: 1.05rem; height: 1.05rem; }

.chat__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .5rem .8rem;
  border-top: 1px solid var(--line);
  background: var(--paper-alt);
  font-size: .72rem;
  color: var(--ink-500);
}

.chat__foot[hidden] { display: none; }

.chat__end {
  border: 0;
  background: none;
  color: var(--ink-500);
  font-size: .72rem;
  cursor: pointer;
  text-decoration: underline;
}

/* On a small screen the panel takes the width it needs to be usable. */
@media (max-width: 26rem) {
  .chat { left: .5rem; right: .5rem; align-items: stretch; }
  .chat__panel { width: auto; max-height: 78vh; }
  .chat__launcher { align-self: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
  .chat__launcher, .chat__dept, .chat__close { transition: none; }
}

/* ============================================================ tech surfaces
 *
 * Azure-tinted texture for the four bands that were flat rectangles: the
 * interior page head, the strip, the closing CTA, and the promo panel.
 *
 * All of it is CSS gradients, no images. That is the same trick the branded
 * hero slide already uses, and the reason is payload: the page head appears on
 * about ten pages, so anything downloaded here is downloaded ten times over a
 * visit. A repeating-linear-gradient grid costs nothing and scales to any
 * width.
 *
 * Two rules make this work and are easy to get wrong:
 *
 *  - Each band needs `position: relative` and `overflow: hidden`, and its
 *    content needs `position: relative; z-index: 1`. An absolutely positioned
 *    ::before paints above static in-flow siblings, so without lifting the
 *    content the texture would cover the heading.
 *
 *  - The grid is masked with a radial-gradient so it fades out rather than
 *    stopping at a hard edge. An unmasked grid reads as a table.
 */

/* ------------------------------------------------- interior page head band */

/* .page-hero is used by domains, faq, team, testimonials, blog-index, plans
   and domain-results; .page-head is the sibling that site/pricing.php uses.
   They get the same treatment so the two never look like different sites. */
.page-hero,
.page-head {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.page-hero::before,
.page-head::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;

  /* A 34px lattice, the same pitch as the dot grid in the hero illustration,
     so the two read as one family. Brand blue at 5% — enough to catch the
     light, not enough to compete with the heading. */
  background-image:
    repeating-linear-gradient(0deg,
      color-mix(in srgb, var(--brand-500) 5%, transparent) 0 1px,
      transparent 1px 34px),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--brand-500) 5%, transparent) 0 1px,
      transparent 1px 34px);

  /* Fades towards the bottom-left, so the grid is densest behind the top-right
     corner where there is no text on any of these pages. */
  -webkit-mask-image: radial-gradient(115% 100% at 100% 0%, #000 10%, transparent 72%);
          mask-image: radial-gradient(115% 100% at 100% 0%, #000 10%, transparent 72%);
}

/* A cool wash in the same corner, to stop the grid looking like graph paper. */
.page-hero::after,
.page-head::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: -55%;
  right: -12%;
  width: 46rem;
  height: 46rem;
  pointer-events: none;
  border-radius: 50%;
  background:
    radial-gradient(circle,
      color-mix(in srgb, var(--tech-400) 16%, transparent) 0%,
      transparent 68%);
}

.page-hero > *,
.page-head > * {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------- the strip band */

.strip {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

/* On the brand gradient the grid has to be white, not blue — blue on blue is
   invisible. Same pitch, so it still belongs to the set. */
.strip::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg,  rgb(255 255 255 / .07) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(90deg, rgb(255 255 255 / .07) 0 1px, transparent 1px 34px);
  -webkit-mask-image: radial-gradient(80% 140% at 50% 0%, #000 0%, transparent 78%);
          mask-image: radial-gradient(80% 140% at 50% 0%, #000 0%, transparent 78%);
}

.strip > * { position: relative; z-index: 1; }

/* ------------------------------------------------------ the closing CTA band */

.cta-band {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg,  rgb(255 255 255 / .06) 0 1px, transparent 1px 34px),
    repeating-linear-gradient(90deg, rgb(255 255 255 / .06) 0 1px, transparent 1px 34px);
  -webkit-mask-image: radial-gradient(90% 120% at 12% 0%, #000 0%, transparent 70%);
          mask-image: radial-gradient(90% 120% at 12% 0%, #000 0%, transparent 70%);
}

/* Cyan bloom in the opposite corner from the grid, so the panel has a
   direction to it rather than being evenly tinted. */
.cta-band::after {
  content: "";
  position: absolute;
  z-index: 0;
  right: -8%;
  bottom: -70%;
  width: 34rem;
  height: 34rem;
  pointer-events: none;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(80 230 255 / .20) 0%, transparent 66%);
}

.cta-band > * { position: relative; z-index: 1; }

/* ------------------------------------------------------- the promo panel */

/* This panel used to hold a 24x24 stroke icon scaled to 45% of its width —
   about eight times its drawn size, so a 2px stroke rendered as a 16px slab.
   It now holds a real illustration (partials/site/tech-art.php), and the panel
   gets the grid behind it. The icon fallback is kept for a block whose art
   name is not in the set, but it is no longer the normal path. */
.promo__media {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.promo__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg,
      color-mix(in srgb, var(--brand-500) 7%, transparent) 0 1px,
      transparent 1px 28px),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--brand-500) 7%, transparent) 0 1px,
      transparent 1px 28px);
  -webkit-mask-image: radial-gradient(100% 100% at 50% 100%, #000 0%, transparent 75%);
          mask-image: radial-gradient(100% 100% at 50% 100%, #000 0%, transparent 75%);
}

.promo__media > * { position: relative; z-index: 1; }

/* The illustration is drawn at its own scale, so it must not inherit the old
   45%-of-container rule that the bare icon needed. */
.promo__media .tech-art {
  width: 78%;
  max-width: 22rem;
  height: auto;
}

/* ============================================================== tech-art
 *
 * The shared illustration set. Every piece is drawn on a 240x180 grid with the
 * same construction rules, which is what makes them read as one family rather
 * than six unrelated pictures:
 *
 *   - 2px strokes on --brand-600, panels filled with --brand-050
 *   - one cyan accent per picture, never two
 *   - no text, so nothing needs translating
 *   - currentColor is never used: these sit on tinted panels, not on body text
 */

.tech-art {
  display: block;
  width: 100%;
  height: auto;
}

/* Empty states get the same artwork at a smaller size, replacing the faint
   46px stroke glyph that used to stand in for one. */
.empty-state .tech-art {
  width: 148px;
  margin: 0 auto 1.1rem;
}

/* No dark-mode override is needed here. The illustrations are built from
   semi-transparent brand and cyan fills rather than white panels, so they sit
   correctly on both the light --brand-050 panel and its dark counterpart. An
   earlier draft of this file carried a :root:not([data-theme="light"]) rule
   OUTSIDE a prefers-color-scheme block, which would have applied in light mode
   too — the dark rules in this stylesheet are always inside the media query,
   and that is why. */

/* --------------------------------------------- page head with an illustration */

/* Used by the six product pages, where the category's icon resolves to an
   illustration. The band keeps its texture; this only adds the second column.

   The art column is dropped below 52rem rather than shrunk. A 240x180 drawing
   scaled into a phone-width sliver reads as a smudge, and it is decorative, so
   losing it costs nothing — whereas squeezing the heading to make room for it
   costs something real. */
.page-hero--art .container {
  display: grid;
  gap: clamp(16px, 3vw, 40px);
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
}

.page-hero--art .page-hero__art { display: none; }

@media (min-width: 52rem) {
  .page-hero--art .container { grid-template-columns: minmax(0, 1fr) minmax(0, 17rem); }
  .page-hero--art .page-hero__art { display: block; }
}

/* The art sits above the band's own ::before grid, which is at z-index 0. */
.page-hero__art {
  position: relative;
  z-index: 1;
}

.page-hero__art .tech-art {
  width: 100%;
  max-width: 17rem;
  margin-inline-start: auto;
}

/* ------------------------------------------- region chip: the multi-region form */

/* With one region the chip is a plain span (see partials/site/region-chip.php).
   With more than one it becomes a <details>, so it opens without JavaScript. */

.topbar-region__pick { position: relative; }

.topbar-region__pick > summary {
  cursor: pointer;
  list-style: none;
}

/* Safari draws its own triangle on a summary; this removes it so the chevron
   below is the only affordance. */
.topbar-region__pick > summary::-webkit-details-marker { display: none; }

.topbar-region__chev {
  width: .8rem;
  height: .8rem;
  opacity: .6;
  transition: transform .15s ease;
}

.topbar-region__pick[open] > summary .topbar-region__chev { transform: rotate(180deg); }

.topbar-region__panel {
  position: absolute;
  right: 0;
  z-index: 60;
  width: max-content;
  min-width: 15rem;
  max-width: min(22rem, calc(100vw - 2rem));
  margin-top: .4rem;
  padding: .8rem .9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow-3);
  /* The top bar sets a small font; the panel is prose and wants the normal one. */
  font-size: var(--step--1);
  line-height: 1.5;
  text-align: left;
}

.topbar-region__lead {
  margin: 0 0 .5rem;
  font-weight: 600;
  color: var(--ink-900);
}

.topbar-region__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.topbar-region__list > li {
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--line);
}

.topbar-region__list > li:last-child { border-bottom: 0; padding-bottom: 0; }

.topbar-region__rname {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
  font-weight: 600;
  color: var(--ink-900);
}

/* The currency code, set apart so it reads as data rather than as part of the
   place name. */
.topbar-region__cur {
  padding: .05rem .35rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--paper-alt);
  color: var(--ink-700);
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.topbar-region__tag {
  padding: .05rem .4rem;
  border-radius: var(--radius-pill, 999px);
  background: var(--brand-050);
  color: var(--brand-on-tint);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.topbar-region__rnote {
  display: block;
  margin-top: .1rem;
  color: var(--ink-500);
  font-weight: 400;
}

.topbar-region__foot {
  margin: .6rem 0 0;
  padding-top: .5rem;
  border-top: 1px solid var(--line);
  color: var(--ink-500);
}

/* On a phone the panel would run off the right edge of a narrow top bar, so it
   is pinned to the viewport instead of to the chip. */
@media (max-width: 30rem) {
  .topbar-region__panel {
    position: fixed;
    right: 1rem;
    left: 1rem;
    width: auto;
    max-width: none;
  }
}
/* ------------------------------------------------- top bar: cursor light */

/* A soft light that follows the pointer across the top bar.
 *
 * Position comes from two custom properties that app.js writes on mousemove.
 * Everything else is CSS, which matters: the only thing JavaScript does per
 * frame is set two numbers, and the compositor does the painting. Animating a
 * background-position or a left offset from script would cost a layout on every
 * mouse move.
 *
 * It is decoration, so it is switched off entirely for reduced motion and on
 * touch, where there is no pointer to follow and the effect would either never
 * appear or stick wherever the last tap landed.
 */
.site-header__topbar {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  /* Off-canvas until the pointer arrives, so nothing shows on load. */
  --cursor-x: -100%;
  --cursor-y: 50%;
}

.site-header__topbar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  background: radial-gradient(
    18rem 8rem at var(--cursor-x) var(--cursor-y),
    color-mix(in srgb, var(--brand-500) 16%, transparent) 0%,
    transparent 70%
  );
}

.site-header__topbar.is-lit::before { opacity: 1; }

/* The bar's own content must sit above the light. */
.site-header__topbar-inner { position: relative; z-index: 1; }

/* A pointer that can hover is the only case where this makes sense. */
@media (hover: none), (pointer: coarse) {
  .site-header__topbar::before { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header__topbar::before { display: none; }
}

/* The links pick up a little of the same warmth as the light passes, which is
   what stops it reading as a stray gradient and makes it feel attached to the
   pointer. */
.topbar-contact a,
.topbar-links a {
  transition: color .2s ease;
}

.topbar-contact a:hover,
.topbar-links a:hover {
  color: var(--brand-text);
}
/* ------------------------------------------- region selector: the options */

/* Each region is a button now, not a list item, because with more than one
   configured it is a real choice. */
.topbar-region__opt {
  display: block;
  width: 100%;
  padding: .35rem .4rem;
  border: 0;
  border-radius: var(--radius-sm, 8px);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .15s ease;
}

.topbar-region__opt:hover { background: var(--brand-050); }

.topbar-region__opt:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: -2px;
}

.topbar-region__list > li.is-current .topbar-region__opt { background: var(--brand-050); }

/* What the detection concluded, above the list. */
.topbar-region__detected {
  margin: 0 0 .5rem;
  color: var(--ink-500);
  font-size: .82rem;
}
/* ============================================== chat widget: presentation
 *
 * Two things were wrong and both were visual rather than functional.
 *
 * The launcher already toggled the panel, but it kept showing a speech bubble
 * labelled "Chat" while sitting on top of the open panel — so it looked like a
 * second, redundant control rather than the way out. It now carries both icons
 * and swaps them on .is-open.
 *
 * And the department picker rendered as three lines of unstyled text per desk,
 * which is what "everything looks plain" meant. Each desk is now a card: an
 * icon tile, the name, what it covers, whether anybody is there, and a chevron.
 */

/* -------------------------------------------------- launcher, both states */

.chat__launcher-icon--close { display: none; }

.chat.is-open .chat__launcher-icon--chat  { display: none; }
.chat.is-open .chat__launcher-icon--close { display: inline-flex; }

/* With the panel open the pill would repeat the panel's own title, so it
   collapses to a round button that reads only as "close". */
.chat.is-open .chat__launcher-text { display: none; }

.chat.is-open .chat__launcher {
  width: 2.9rem;
  height: 2.9rem;
  padding: 0;
  justify-content: center;
  border-radius: 999px;
}

/* The unread count is meaningless while you are looking at the thread. */
.chat.is-open .chat__unread { display: none; }

/* ------------------------------------------------------------- the header */

.chat__head { align-items: center; gap: .7rem; }

.chat__brand {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  flex: none;
  border-radius: 8px;
  background: rgb(255 255 255 / .16);
}

/* The mark is drawn in its own blues, which disappear on the brand-coloured
   header, so here it is forced to white. */
.chat__brand .brand-logo { width: 1.35rem; height: auto; }
.chat__brand .brand-logo polygon,
.chat__brand .brand-logo rect { fill: #fff !important; }

.chat__head-text { min-width: 0; }

/* ------------------------------------------------------- department cards */

.chat__departments { gap: .6rem; }

.chat__dept {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: .75rem;
  width: 100%;
  padding: .7rem .8rem;
  text-align: left;
}

.chat__dept-icon {
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  flex: none;
  border-radius: 10px;
  background: var(--brand-050);
  color: var(--brand-on-tint);
}

.chat__dept-icon svg { width: 1.25rem; height: 1.25rem; }

.chat__dept:hover .chat__dept-icon {
  background: var(--brand-600);
  color: #fff;
}

.chat__dept-main {
  display: grid;
  gap: .1rem;
  min-width: 0;
}

.chat__dept-name {
  font-weight: 700;
  color: var(--ink-900);
  font-size: .95rem;
}

.chat__dept-blurb {
  color: var(--ink-500);
  font-size: .8rem;
  line-height: 1.35;
}

/* Availability is the fact that decides whether someone waits or leaves a
   message, so it gets its own row and its own colour rather than being a third
   grey line. */
.chat__dept-avail {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  margin-top: .15rem;
  font-size: .74rem;
  font-weight: 600;
}

.chat__dept-avail.is-online { color: var(--accent-700); }
.chat__dept-avail.is-away   { color: var(--ink-500); }

.chat__dept-go {
  color: var(--ink-500);
  font-size: 1.3rem;
  line-height: 1;
  transition: transform .15s ease, color .15s ease;
}

.chat__dept:hover .chat__dept-go {
  color: var(--brand-text);
  transform: translateX(2px);
}

/* ------------------------------------------------------ message timestamps */

.chat__msg { position: relative; }

.chat__msg-time {
  display: block;
  margin-top: .2rem;
  font-size: .66rem;
  font-variant-numeric: tabular-nums;
  opacity: .7;
  text-align: right;
}

.chat__msg--agent .chat__msg-time { text-align: left; }

/* A little more air between turns than within one, so a back-and-forth reads
   as a conversation rather than a list. */
.chat__messages { gap: .7rem; }
.chat__messages > .chat__msg--system + .chat__msg { margin-top: .2rem; }

/* ------------------------------------------- header menu: never break a label */

/* The labels were wrapping mid-label — "VPS &" / "Dedicated" on two lines —
   even at 1180px where the three header regions together needed only 1077px of
   the 1165px available. The cause was simply that .nav__link had no
   white-space rule, so the grid's auto track sized itself to the WRAPPED
   content and then reported that it fitted.
   Renaming "Website Builder" to "AI Website Builder" is what pushed it over. */
.nav__link,
.dropdown__link { white-space: nowrap; }

/* Between 992px and 1300px the five labels plus the logo and the four buttons
   are genuinely tight, so the menu tightens rather than wrapping or pushing the
   logo out. Below 992px the drawer takes over and none of this applies. */
@media (min-width: 992px) and (max-width: 1300px) {
  .site-header__bar-inner { gap: .6rem; }
  .nav__list { gap: .1rem; }
  .nav__link { padding-inline: .5rem; font-size: .92rem; }
  .nav__cta { gap: .3rem; }
  .nav__util { padding-inline: .4rem; }

  /* At exactly 992px — where the desktop grid takes over from the drawer —
     the row needed 1018px and had 992. The logo is the largest single item
     and 2rem still reads clearly, where squeezing the menu further would
     start truncating labels. 190px becomes about 162px, which covers it. */
  .site-header .brand-logo { height: 2rem; }

  /* "Cart" and "Help" read fine as icons at this width; their labels are the
     first thing worth giving up, and both keep an aria-label so nothing is
     lost to a screen reader.

     Measured: at 1024px the row still ran 32px past the viewport, because
     minmax(max-content, 1fr) on the outer tracks — which is what stops the
     logo collapsing — will not let the grid shrink below its content. The
     two labels together are about 70px, so dropping both is what buys the
     room rather than squeezing the logo again. */
  .nav__util--cart .nav__util-text,
  .nav__util:not(.nav__util--cart) span { display: none; }
}

/* ================================== hero artwork: one box for every slide
 *
 * The slides used two different illustrations at two different scales: slide
 * one the detailed 520x420 hero drawing, the rest 240x180 pieces from the
 * shared set. Same markup slot, different footprints — so the picture jumped in
 * size as the slider advanced, which is what "some are big some are small"
 * meant.
 *
 * Fixed by giving the media slot ONE box with a fixed ratio and letting each
 * SVG centre inside it. An SVG with a viewBox honours preserveAspectRatio, so
 * a 4:3 piece and a 1.24:1 piece both sit centred in the same rectangle at
 * their own proportions, and the footprint stops moving.
 *
 * The composed look comes from CSS behind the art rather than from more SVG.
 * That is not a shortcut: the homepage is close to its 120 KB budget, and four
 * richly-drawn hero illustrations would be about 20 KB of inline markup for
 * pictures only one of which is visible at a time. A gradient grid costs
 * nothing and gives every slide the same technical backdrop.
 */

@media (min-width: 900px) {
  .hero__media {
    position: relative;
    isolation: isolate;
    /* The canonical art box. Every slide gets exactly this. */
    width: min(100%, 30rem);
    aspect-ratio: 13 / 10;
    place-items: center;
  }

  /* The shared backdrop: a lattice fading out from the top right, the same
     34px pitch as the page-head and strip textures, so the hero belongs to the
     same family. */
  .hero__media::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    border-radius: var(--radius-lg);
    background-image:
      repeating-linear-gradient(0deg,  rgb(255 255 255 / .06) 0 1px, transparent 1px 34px),
      repeating-linear-gradient(90deg, rgb(255 255 255 / .06) 0 1px, transparent 1px 34px);
    -webkit-mask-image: radial-gradient(120% 110% at 78% 12%, #000 8%, transparent 76%);
            mask-image: radial-gradient(120% 110% at 78% 12%, #000 8%, transparent 76%);
  }

  /* A cool bloom behind the focal object, so the art sits in light rather than
     floating on a flat panel. */
  .hero__media::after {
    content: "";
    position: absolute;
    z-index: 0;
    top: 4%;
    right: -6%;
    width: 78%;
    aspect-ratio: 1;
    pointer-events: none;
    border-radius: 50%;
    background: radial-gradient(circle, rgb(80 230 255 / .17) 0%, transparent 68%);
  }

  /* Both kinds of artwork, and an uploaded image, obey the one box. */
  .hero__media > * {
    position: relative;
    z-index: 1;
    max-width: 100%;
    max-height: 100%;
  }

  .hero__media .hero__art,
  .hero__media .hero__art-piece {
    width: 100%;
    height: 100%;
    /* Centred at its own proportions inside the shared box. */
    object-fit: contain;
  }

  /* The line pieces are drawn on a 240x180 canvas, so in a box this size they
     would render hairline-thin. Thickening the strokes here keeps them reading
     as deliberate line art at hero scale rather than as a faint sketch. */
  .hero__media .hero__art-piece [stroke-width="2"] { stroke-width: 2.6; }

  .hero__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-lg);
  }
}

/* On the light slide the white lattice and bloom are invisible, so they are
   swapped for the brand tint. */
@media (min-width: 900px) {
  .hero__slide--light .hero__media::before {
    background-image:
      repeating-linear-gradient(0deg,
        color-mix(in srgb, var(--brand-500) 8%, transparent) 0 1px, transparent 1px 34px),
      repeating-linear-gradient(90deg,
        color-mix(in srgb, var(--brand-500) 8%, transparent) 0 1px, transparent 1px 34px);
  }

  .hero__slide--light .hero__media::after {
    background: radial-gradient(circle,
      color-mix(in srgb, var(--tech-500) 18%, transparent) 0%, transparent 68%);
  }
}

/* ------------------------------------------------------------- site search */

/* The top-bar box. `flex: 1 1 auto` with a max-width is what makes it
   "flexible": it takes the space the contact details and the region chip leave
   and no more, so the bar stays balanced at any width instead of the box being
   a fixed size that is wrong at most of them. */
.site-search {
  position: relative;
  display: flex;
  align-items: center;
}

.site-search--bar {
  flex: 0 1 auto;
  width: 100%;
  max-width: 15rem;
  min-width: 7rem;
  margin-inline: auto;
}

.site-search__icon {
  position: absolute;
  left: .55rem;
  display: inline-flex;
  pointer-events: none;
  color: var(--ink-500);
}

.site-search__icon .icon { width: .95rem; height: .95rem; }

.site-search__input {
  width: 100%;
  padding: .3rem .7rem .3rem 1.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill, 999px);
  background: var(--paper);
  color: var(--ink-900);
  font: inherit;
  font-size: var(--step--1);
  line-height: 1.5;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.site-search__input::placeholder { color: var(--ink-500); }

.site-search__input:focus-visible {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 22%, transparent);
}

/* The results page repeats the field at full size with a real button. */
.site-search--page {
  gap: .6rem;
  max-width: 44rem;
  margin-bottom: 2rem;
}

.site-search--page .field__input { padding-left: 2.3rem; }
.site-search--page .site-search__icon { left: .8rem; }
.site-search--page .site-search__icon .icon { width: 1.1rem; height: 1.1rem; }

/* Below this the top bar has only room for the essentials; the box is on the
   results page and reachable from the footer. */
@media (max-width: 56rem) {
  .site-search--bar { display: none; }
}

/* ------------------------------------------------------- search results */

.search-group { margin-bottom: 2.2rem; }

.search-group__head {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 .8rem;
  font-size: var(--step-1);
}

.search-group__head .icon { width: 1.15rem; height: 1.15rem; color: var(--brand-text); }

.search-group__count {
  padding: .05rem .45rem;
  border-radius: var(--radius-pill, 999px);
  background: var(--brand-050);
  color: var(--brand-on-tint);
  font-size: .72rem;
  font-weight: 700;
}

.search-results {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .5rem;
}

.search-results > li { margin: 0; }

.search-result {
  display: grid;
  gap: .15rem;
  padding: .8rem .95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease, transform .15s ease;
}

.search-result:hover {
  border-color: var(--brand-500);
  background: var(--brand-050);
  transform: translateX(2px);
  text-decoration: none;
}

.search-result__title {
  font-weight: 700;
  color: var(--ink-900);
}

.search-result__body {
  color: var(--ink-500);
  font-size: var(--step--1);
  line-height: 1.5;
}
/* --------------------------------------- top bar: three tracks, search centred */

/* The bar was a flex row with `justify-content: space-between`. That cannot
   centre a middle item between two sides of different widths — the contact
   details are wider than the region chip, so the search box sat 233px right of
   centre — and with three children it ran out of room and wrapped to two rows.
   A grid with equal outer tracks centres the middle one properly, the same
   technique the menu bar uses. */
@media (min-width: 56rem) {
  .site-header__topbar-inner {
    display: grid;
    /* Deliberately small. A wide box pushed the contact details and the
       region chip onto a second row; the bar staying on one line matters
       more than the box being roomy. 15rem shows roughly 24 characters,
       which is more than any search anyone types here. */
    grid-template-columns: minmax(0, 1fr) minmax(7rem, 15rem) minmax(0, 1fr);
    flex-wrap: nowrap;
    gap: 1rem;
    align-items: center;
  }

  /* The search is already margin: auto within its track; the track does the
     centring, so that is now redundant but harmless. */
  .site-header__topbar-inner > .site-search--bar { grid-column: 2; }
  .site-header__topbar-inner > .topbar-contact   { grid-column: 1; justify-self: start; }
  .site-header__topbar-inner > .topbar-links     { grid-column: 3; justify-self: end; }

  /* Neither side may wrap: a two-line top bar pushes the whole page down. The
     email address is the first thing to give up when space runs short — the
     phone number is the one people act on. */
  .topbar-contact,
  .topbar-links { flex-wrap: nowrap; min-width: 0; }

  /* nowrap on the list stops the ROW wrapping; without this the items still
     shrink and break their own text, which turned "+1 8555 012345" into two
     lines mid-number. A phone number that wraps is a phone number nobody
     can read at a glance. */
  .topbar-contact li,
  .topbar-links li,
  .topbar-contact a,
  .topbar-links a { white-space: nowrap; }
}

/* Between 56rem and 76rem all three fit only if the secondary contact details
   step aside. They are still on the contact page and in the footer. */
/* Measured, not guessed. At 1280px the three blocks came to 1264px inside a
   1200px container, so the contact list wrapped and the bar became two rows
   48px tall. The alternate phone, the email and the region note are the
   three widest things that are also the least load-bearing — all three are
   on the contact page and in the footer — so they step aside until there is
   genuinely room. Above 90rem everything fits and they all come back. */
@media (min-width: 56rem) and (max-width: 90rem) {
  .topbar-contact .hide-sm { display: none; }
  .topbar-region__note { display: none; }
}

/* ================================================ chat widget: corrections
 *
 * Four things, all reported from looking at it:
 *
 *  1. Two crosses. Turning the launcher into an X gave the open panel two ways
 *     to close it — the header's X and the launcher sitting just above it. The
 *     launcher now hides entirely while the panel is open, so the header's X is
 *     the only one. (The launcher keeps both icons in its markup; the close one
 *     simply never shows. Harmless, and it means reverting is one line.)
 *
 *  2. The intro wrapped to two lines. The panel is widened and the line set to
 *     nowrap, sized so the shipped wording fits with room to spare.
 *
 *  3. The header blue changed between themes, because it was built from
 *     --brand-700/--brand-500 and those are remapped lighter for dark mode. The
 *     header is a coloured surface, not themed chrome: it is now pinned to the
 *     light-theme values so it is the same blue in both.
 *
 *  4. "Chat to us" inherited its colour. Now explicitly white, along with the
 *     status line beneath it.
 */

/* 1 ------------------------------------------------------------------------ */

.chat.is-open .chat__launcher { display: none; }

/* 2 ------------------------------------------------------------------------ */

/* 25rem gives about 368px of content once the 1rem padding either side is
   taken off. The shipped intro is roughly 344px at .78rem, so it fits with
   headroom rather than exactly. */
.chat__panel { width: min(94vw, 25rem); }

.chat__intro {
  white-space: nowrap;
  /* Measured at .78rem the line was 366px inside 366px — it fitted with
     nothing to spare, and the first system without Segoe UI would have
     clipped it. .72rem leaves about 30px of headroom. */
  font-size: .72rem;
  /* If an owner rewrites the intro longer than the panel, an ellipsis is a far
     better failure than a silently clipped word. */
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 3 ------------------------------------------------------------------------ */

/* Back on the tokens. These used to be literals, because the ramp was remapped
   for dark mode and the header came out a different blue there; the ramp is now
   the same in both themes, so the workaround would only hide the next change. */
.chat__head {
  background: linear-gradient(135deg, var(--brand-700), var(--brand-500));
  color: #fff;
}

/* 4 ------------------------------------------------------------------------ */

.chat__title { color: #fff; }
.chat__status { color: #fff; opacity: .88; }

/* The header sits on a fixed blue in both themes, so its close button and the
   brand tile must not follow the theme either. */
.chat__close { color: #fff; }
.chat__close:hover { background: rgb(255 255 255 / .28); }
.chat__brand { background: rgb(255 255 255 / .18); }

/* 10 ----------------------------------------------------------------------- */

/* Two-step verification, and three utilities the customer area was already
   asking for.
   ------------------------------------------------------------------------- */

/* .muted and .small are used fifteen times across the customer views and were
   only ever defined in admin.css, so every hint in the account area has been
   rendering at full body colour. */
.muted { color: var(--ink-500); }
.small { font-size: var(--step--1); }

/* A button that reads as a link. Used where the action has to be a POST — a
   sign-out, mostly — and dressing it as a button would overstate it. */
.btn-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-text);
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: .2em;
}
.btn-link:hover { color: var(--brand-on-tint); }

/* A short form that sits on one line until there is no room for it. */
.form--inline {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: .75rem;
}
.form--inline .field { margin: 0; flex: 1 1 12rem; }

/* The code box. Wide-tracked and tabular so six digits are easy to check
   against the phone, and sized in ch so it cannot end up narrower than the
   thing it holds. */
.field__input--code {
  width: 9ch;
  font-family: var(--font-mono, ui-monospace, "SFMono-Regular", "Consolas", monospace);
  font-size: 1.35rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: .22em;
  text-align: center;
}

/* The enrolment steps. Numbered, because the order matters — scan, or type the
   key, then confirm. */
.setup-steps {
  margin: 1.5rem 0 0;
  padding: 0 0 0 1.6rem;
  display: grid;
  gap: 1.75rem;
}
.setup-steps > li { padding-left: .35rem; }
.setup-steps h2 {
  margin: 0 0 .6rem;
  font-size: var(--step-0);
  font-weight: 700;
}

/* The QR code keeps a white ground of its own regardless of the theme: a
   scanner needs the contrast, and inverting a QR code stops most of them
   reading it at all. */
.setup-qr {
  display: inline-block;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md, 10px);
  background: #fff;
  line-height: 0;
}
.setup-qr .qr { display: block; width: 200px; height: 200px; }

.setup-secret {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem;
  margin: .5rem 0;
}
.setup-secret code {
  padding: .45rem .7rem;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: var(--paper-alt);
  font-size: 1.05rem;
  letter-spacing: .08em;
  word-break: break-all;
}

/* Recovery codes. Two columns where there is room, one where there is not, and
   monospaced so an I and a 1 can be told apart — which is the whole reason the
   generator avoids those characters in the first place. */
.recovery-codes {
  margin: 1.25rem 0;
  padding: 1rem 1rem 1rem 2.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md, 10px);
  background: var(--paper-alt);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .5rem 1.5rem;
}
.recovery-codes code {
  font-size: 1.05rem;
  letter-spacing: .06em;
}

.auth__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: 1.5rem;
}

/* The "I do not have my phone" disclosure. Closed by default so the six-digit
   box stays the obvious thing to do. */
.auth__aside {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.auth__aside > summary {
  cursor: pointer;
  color: var(--brand-text);
  font-weight: 600;
}
.auth__aside > p { margin: .75rem 0 0; }

.badge--success { background: var(--accent-050); color: var(--accent-700); }

/* Printing the recovery codes should give the codes, not the furniture around
   them. */
@media print {
  .recovery-codes { border-color: #999; background: #fff; }
  .auth__actions,
  .site-header,
  .site-footer,
  .chat { display: none !important; }
}
