/* LAN-SERVERS -- marketing site theme.
 *
 * Structure and density only. Every colour, size and font name comes from the brand's
 * tokens.css, which loads first; swapping the brand swaps all of it without touching
 * this file. The @font-face rules live with the brand too, next to the font files.
 *
 * Ported verbatim from the approved brand kit (site/styles.css, v1.0, Sept 2026).
 * Keep the section rhythm it encodes: dark header -> dark hero -> dark proof strip ->
 * light sections -> dark CTA band -> dark footer. Light sections carry .theme-light,
 * which flips --accent from cyan to deep cyan -- BRAND.md section 3: never #22D3EE on white.
 *
 * THE HEADER, THE FOOTER, THE BUTTONS AND .container ARE NOT IN THIS FILE. They are in
 * chrome.css, next to it, which loads first - because the client area uses the same
 * ones, and one copy is the only way the two stay the same (Todor, 2026-09-22).
 */


*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--navy);
  color: var(--text-dark-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
a { color: inherit; text-decoration: none; }
img, svg { display: block; }
h1, h2, h3, p { margin: 0; }

.mono { font-family: var(--font-mono); }
.eyebrow { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: 0.14em; text-transform: uppercase; }

/* Buttons, the header, the logo and the mobile menu: chrome.css. */

/* ---------- Hero (dark) ---------- */
.hero .container { min-height: 560px; display: flex; align-items: center; justify-content: space-between; gap: 48px; padding-top: 48px; padding-bottom: 48px; }
.hero-copy { display: flex; flex-direction: column; gap: 26px; max-width: 640px; }
.hero-copy .eyebrow { color: var(--accent); }
.hero h1 { font-size: var(--fs-display); font-weight: 600; line-height: var(--lh-tight); letter-spacing: -0.02em; }
.hero h1 .accent, .accent { color: var(--accent); }
.hero .lede { font-size: 20px; line-height: 1.45; color: var(--text-dark-secondary); max-width: 560px; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }
/* The mark as the hero graphic (pages with no map): the wordmark is not repeated
   there, so only the mark shows and it is sized by the box. */
.hero-mark { width: 340px; height: 340px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.hero-mark .brand-logo { color: var(--cyan); }
.hero-mark .brand-logo .word { display: none; }
.hero-mark .brand-logo .mark svg { height: 340px; }

/* ---------- Proof strip (dark, raised) ---------- */
.proof { background: var(--surface-dark); border-top: 1px solid var(--border-dark); border-bottom: 1px solid var(--border-dark); }
.proof .container { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; padding-top: 22px; padding-bottom: 22px; }
.proof strong { display: block; font-size: 22px; font-weight: 600; line-height: 1.2; }
.proof span { font-size: 14px; color: var(--text-dark-secondary); }

/* ---------- Light sections ---------- */
.section { padding: var(--space-8) 0; }
.section.light { background: var(--surface-light-alt); color: var(--text-light-primary); }
.section.white { background: var(--surface-light); color: var(--text-light-primary); border-top: 1px solid var(--border-light); }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 32px; flex-wrap: wrap; }
.section h2 { font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.015em; }
.section-head .aside { font-size: 16px; color: var(--text-light-secondary); }
.section-head a.aside { color: var(--cyan-deep); font-weight: 500; }

.card { background: var(--surface-light); border: 1px solid var(--border-light); border-radius: var(--radius-lg); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }

/* Pillars */
.pillar { padding: 24px; display: flex; flex-direction: column; gap: 12px; }
.pillar svg { width: 40px; height: 40px; color: var(--cyan-deep); }
.pillar h3 { font-size: var(--fs-h3); font-weight: 600; }
.pillar p { font-size: 15px; color: var(--text-light-secondary); }

/* Plans */
.plan { padding: 26px 24px; display: flex; flex-direction: column; gap: 14px; }
.plan .label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-light-muted); }
.plan .price { font-size: 30px; font-weight: 600; line-height: 1; }
.plan .price small { font-size: 15px; font-weight: 400; color: var(--text-light-muted); }
.plan .specs { display: flex; flex-direction: column; }
.plan .spec { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; color: var(--text-light-body); padding: 9px 0; border-bottom: 1px solid var(--border-light-soft); }
.plan .spec:last-child { border-bottom: 0; }
.plan .spec b { font-weight: 500; color: var(--text-light-primary); }
.plan .btn { margin-top: auto; min-height: 44px; }
.plan.featured { border-color: var(--cyan-deep); box-shadow: 0 0 0 1px var(--cyan-deep); }
.plan.featured .label { color: var(--cyan-deep); }
.plan .badge { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; padding: 3px 8px; border-radius: 4px; background: var(--cyan-deep); color: #fff; }
/* The label and the badge on one line (was an inline style; the site is built for a strict CSP). */
.plan-top { display: flex; justify-content: space-between; align-items: center; }
.plan.custom { background: var(--navy); color: var(--text-dark-primary); border-color: var(--navy); --accent: var(--cyan); --accent-fg: var(--navy); }
.plan.custom .label { color: var(--cyan); }
.plan.custom p { font-size: 15px; color: var(--text-dark-secondary); }
/* Every package the panel sells, on /dedicated-servers (components/packages.php, 2026-09-24). */
.packages-lede { margin: -16px 0 28px; max-width: 72ch; font-size: 16px; line-height: 1.6; color: var(--text-light-body); }

/* ---- The list of ready servers: filters on the left, one row per server (2026-10-08) ----
   Laid out like Hetzner's server finder, at Todor's request. The filters are a plain GET
   form; js/servers.js marks the page .srv-live and swaps the results in place, so the Apply
   button is only for a visitor with no script. */
.srv-finder { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 24px; align-items: start; }
.srv-filters { padding: 20px; display: flex; flex-direction: column; gap: 16px; }
.srv-filters-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.srv-filters-head h3 { font-size: 16px; font-weight: 600; }
.srv-filters-head a { font-size: 14px; color: var(--cyan-deep); font-weight: 500; }
.srv-field { display: flex; flex-direction: column; gap: 6px; }
.srv-field label, .srv-sort label {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500;
}
.srv-field select, .srv-sort select {
  font: inherit; font-size: 15px; color: var(--text-light-primary); width: 100%;
  min-height: 42px; padding: 8px 10px;
  background: var(--surface-light); border: 1px solid var(--border-light); border-radius: var(--radius-sm);
}
.srv-field select:focus-visible, .srv-sort select:focus-visible, .srv-check input:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 1px; }
.srv-range output { font-size: 15px; font-weight: 500; color: var(--text-light-primary); font-variant-numeric: tabular-nums; }
.srv-range input[type="range"] { width: 100%; margin: 2px 0; accent-color: var(--cyan-deep); height: 22px; cursor: pointer; }
.srv-range input[type="range"]:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 4px; }
.srv-range-ends { display: flex; justify-content: space-between; font-family: var(--font-mono); font-size: 11px; color: var(--text-light-muted); }
.srv-check { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 15px; color: var(--text-light-primary); }
.srv-check input { width: 18px; height: 18px; margin: 0; accent-color: var(--cyan-deep); flex: none; }
.srv-apply { align-self: flex-start; }
.srv-live .srv-apply { display: none; }

.srv-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.srv-count { font-size: 15px; color: var(--text-light-secondary); }
.srv-sort { display: flex; align-items: center; gap: 10px; }
.srv-sort select { width: auto; }
.srv-results { transition: opacity .12s linear; }
.srv-results[aria-busy="true"] { opacity: .55; }

.srv-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.srv-row { display: grid; grid-template-columns: 190px minmax(0, 1fr) 200px; gap: 24px; padding: 22px 24px; align-items: center; }
.srv-name { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.srv-name h3 { font-size: 18px; font-weight: 600; line-height: 1.25; }
.srv-name .badge, .srv-buy .badge { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; padding: 3px 8px; border-radius: 4px; background: var(--cyan-deep); color: #fff; }
.srv-model { font-weight: 600; font-size: 15px; margin-bottom: 8px; }
/* The maker's logo under the In stock badge (2026-11-11). The makers' current logos, both
   wordmarks; heights chosen so the long "Dell Technologies" and the short "HPE" read at
   about the same weight. */
.srv-make { display: block; width: auto; height: 17px; margin-top: 10px; }
.srv-make.is-hpe { height: 22px; }
.srv-specs dl { margin: 0; display: flex; flex-direction: column; gap: 4px; }
.srv-specs dl div { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 12px; font-size: 14px; }
.srv-specs dt { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-light-muted); padding-top: 2px; }
.srv-specs dd { margin: 0; color: var(--text-light-primary); }
.srv-buy { display: flex; flex-direction: column; align-items: stretch; gap: 4px; text-align: right; }
.srv-price { font-size: 28px; font-weight: 600; line-height: 1.1; }
.srv-price small { font-size: 14px; font-weight: 400; color: var(--text-light-muted); }
.srv-vat { font-size: 12px; color: var(--text-light-muted); margin-bottom: 10px; }
.srv-buy .btn { min-height: 44px; }
.srv-empty { padding: 22px 24px; border: 1px dashed var(--border-light); border-radius: var(--radius-lg); color: var(--text-light-secondary); }
.srv-empty a { color: var(--cyan-deep); font-weight: 500; }
.srv-custom { background: var(--navy); color: var(--text-dark-primary); border-color: var(--navy); --accent: var(--cyan); --accent-fg: var(--navy); }
.srv-custom .srv-specs p { font-size: 15px; color: var(--text-dark-secondary); }
.srv-custom .srv-price { font-size: 22px; }

@media (max-width: 1024px) {
  .srv-row { grid-template-columns: minmax(0, 1fr) 180px; }
  .srv-name { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; }
  /* With the name and the badge in one line, the logo closes it on the right. */
  .srv-make { margin: 0 0 0 auto; align-self: center; height: 15px; }
  .srv-make.is-hpe { height: 19px; }
}
@media (max-width: 800px) {
  .srv-finder { grid-template-columns: 1fr; }
  .srv-filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
  .srv-filters-head, .srv-range, .srv-apply { grid-column: 1 / -1; }
  .srv-row { grid-template-columns: 1fr; gap: 14px; padding: 18px; }
  .srv-buy { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; text-align: left; gap: 4px 12px; }
  .srv-vat { margin-bottom: 0; }
  .srv-buy .btn { flex: 1 0 100%; }
}
@media (max-width: 520px) {
  /* The filters stay two to a row on a phone: one to a row they push the list a screen down. */
  .srv-filters { padding: 16px; gap: 10px 12px; }
  .srv-field select { font-size: 14px; padding: 8px 6px; }
  .srv-specs dl div { grid-template-columns: 72px minmax(0, 1fr); }
}

/* Network */
.network .container { display: flex; align-items: center; gap: 64px; }
.network-graphic { width: 292px; height: 292px; flex-shrink: 0; color: var(--cyan-deep); }
.network-copy { display: flex; flex-direction: column; gap: 18px; max-width: 700px; }
.network-copy .eyebrow { color: var(--cyan-deep); }
.network-copy p { font-size: 17px; color: var(--text-light-secondary); }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { font-family: var(--font-mono); font-size: 12px; padding: 6px 10px; border-radius: var(--radius-sm); background: #F1F5F9; color: var(--text-light-body); }
.chip.more { background: transparent; color: var(--cyan-deep); }

/* Data center */
.dc-card { padding: 22px 24px; display: flex; flex-direction: column; gap: 8px; }
.dc-card h3 { font-size: 18px; font-weight: 600; }
.dc-card p { font-size: 15px; color: var(--text-light-secondary); }

/* ---------- CTA band (dark) ---------- */
.cta-band { background: var(--navy); color: var(--text-dark-primary); }
.cta-band .container { min-height: 200px; display: flex; align-items: center; justify-content: space-between; gap: 32px; padding-top: 40px; padding-bottom: 40px; flex-wrap: wrap; }
.cta-band h2 { font-size: 30px; font-weight: 600; letter-spacing: -0.015em; }
.cta-band p { color: var(--text-dark-secondary); }
.cta-actions { display: flex; gap: 14px; flex-wrap: wrap; }

/* The footer: chrome.css. */

/* ---------- Responsive ---------- */
/* The header's and the footer's own breakpoints are in chrome.css, at the same widths. */
@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .proof .container { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-mark { width: 260px; height: 260px; }
  .hero-mark .brand-logo .mark svg { height: 260px; }
}
@media (max-width: 800px) {
  .hero .container { flex-direction: column-reverse; align-items: flex-start; min-height: 0; }
  .hero-mark { width: 180px; height: 180px; }
  .hero-mark .brand-logo .mark svg { height: 180px; }
  .grid-3 { grid-template-columns: 1fr; }
  .network .container { flex-direction: column; align-items: flex-start; gap: 32px; }
  .network-graphic { width: 200px; height: 200px; }
}
@media (max-width: 520px) {
  .grid-4, .proof .container { grid-template-columns: 1fr; }
  .section { padding: var(--space-7) 0; }
  /* A link into a page puts the section's top edge under the 65px sticky header. Wider
     than this a section's 64px of padding is what the header covers, and the heading
     shows just below it. Here the padding is 48px, so the heading's top was cut off,
     on the footer's Pricing (#pricing) most of all (2026-11-11). 24px more brings the
     heading clear, where it sits on a wide screen. /legal clears the header its own way. */
  section[id], main > div[id] { scroll-margin-top: 24px; }
}

/* =========================================================================
   Components beyond the homepage. Same vocabulary: light sections carry
   .theme-light, cards are .card, labels and figures are mono, the accent
   comes from --accent so it is cyan on dark and deep cyan on light without
   a second rule anywhere.
   ========================================================================= */

/* ---------- Check list: the bullet shape used through the product pages ---
   The tick is drawn with a border on a rotated pseudo-element rather than an
   SVG or an emoji: it inherits --accent, scales with the text, and costs no
   request. */
.checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.checks li { position: relative; padding-left: 30px; font-size: 15px; color: var(--text-light-body); }
.checks li::before {
  content: ""; position: absolute; left: 4px; top: 6px;
  width: 6px; height: 11px; border: solid var(--accent);
  border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.section:not(.theme-light) .checks li { color: var(--text-dark-secondary); }
/* A long list in two columns (the network filter on /ddos-protection, 2026-11-11). */
.checks.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 32px; }
@media (max-width: 700px) { .checks.two { grid-template-columns: 1fr; } }

/* ---------- Feature block: image one side, copy the other, alternating ---- */
.feature { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 64px; }
.feature + .feature { margin-top: var(--space-8); }
.feature.flip .feature-media { order: 2; }
.feature-media picture img, .feature-media > img { width: 100%; height: auto; border-radius: var(--radius-lg); display: block; }
.feature-copy { display: flex; flex-direction: column; gap: 16px; }
.feature-copy .eyebrow { color: var(--accent); }
.feature-copy h3 { font-size: 26px; font-weight: 600; letter-spacing: -0.015em; }
.feature-copy p { font-size: 16px; color: var(--text-light-secondary); }

/* ---------- Stat row: figures that are not the dark proof strip ----------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 24px; }
.stat { display: flex; flex-direction: column; gap: 4px; }
.stat b { font-size: 30px; font-weight: 600; line-height: 1.1; letter-spacing: -0.02em; }
.stat span { font-size: 14px; color: var(--text-light-secondary); }
.stat .unit { font-family: var(--font-mono); font-size: 12px; letter-spacing: var(--track-caps);
              text-transform: uppercase; color: var(--text-light-muted); }

/* ---------- Spec / facts table -------------------------------------------
   Two columns, label left, value right, one hairline between rows. The same
   shape as a plan card's spec list, at full width -- deliberately, so a spec
   reads identically wherever it appears. */
.spec-table { width: 100%; border-collapse: collapse; }
.spec-table caption { text-align: left; font-family: var(--font-mono); font-size: var(--fs-caption);
                      letter-spacing: var(--track-caps); text-transform: uppercase;
                      color: var(--text-light-muted); padding-bottom: 10px; }
.spec-table th, .spec-table td { text-align: left; padding: 11px 0; border-bottom: 1px solid var(--border-light-soft);
                                 font-size: 15px; vertical-align: top; }
.spec-table th { font-weight: 500; color: var(--text-light-secondary); width: 38%; }
.spec-table td { color: var(--text-light-primary); font-weight: 500; }
.spec-table tr:last-child th, .spec-table tr:last-child td { border-bottom: 0; }
.spec-table td .mono, .spec-table td code { font-family: var(--font-mono); font-size: 14px; }

/* ---------- FAQ accordion, no JavaScript ---------------------------------
   <details>/<summary>. The marker is replaced by a chevron drawn from two
   borders, rotated on open. Nothing here needs a script, which keeps the
   strict CSP intact -- the moment a component needs inline JS, that policy
   has to be widened for every page. */
.faq { display: flex; flex-direction: column; }
.faq details { border-bottom: 1px solid var(--border-light); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 0; cursor: pointer; list-style: none;
  font-size: 17px; font-weight: 500; color: var(--text-light-primary);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 9px; height: 9px;
  border: solid var(--text-light-muted); border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .15s cubic-bezier(.4, 0, .2, 1);
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.faq details[open] summary { color: var(--accent); }
.faq .answer { padding: 0 0 20px; font-size: 15px; line-height: 1.6; color: var(--text-light-secondary); max-width: 70ch; }
.faq .answer p + p { margin-top: 10px; }
.faq-group + .faq-group { margin-top: var(--space-7); }
.faq-group > h3 { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
                  text-transform: uppercase; color: var(--text-light-muted); margin-bottom: 4px; }

/* ---------- Badge pills under a hero -------------------------------------- */
.pills { display: flex; flex-wrap: wrap; gap: 10px; }
.pill { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em;
        padding: 7px 12px; border-radius: 999px; border: 1px solid var(--border-dark);
        color: var(--text-dark-secondary); }

/* ---------- Numbered claims ------------------------------------------------ */
.claims { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 28px; }
.claim { display: flex; flex-direction: column; gap: 8px; }
.claim .n { font-family: var(--font-mono); font-size: 13px; color: var(--accent); }
.claim h3 { font-size: 17px; font-weight: 600; }
.claim p { font-size: 15px; color: var(--text-light-secondary); }

@media (max-width: 800px) {
  .feature { grid-template-columns: 1fr; gap: 28px; }
  .feature.flip .feature-media { order: 0; }
  .spec-table th { width: 46%; }
}

/* ---------- Section wrapper -----------------------------------------------
   .section.dark is the third surface, alongside .light and .white. It carries
   no .theme-light, so --accent stays the on-dark cyan. */
.section.dark { background: var(--navy); color: var(--text-dark-primary); }
.section.dark .section-head .aside { color: var(--cyan); }
.section.dark h2, .section.dark h3 { color: var(--text-dark-primary); }
.section.dark p { color: var(--text-dark-secondary); }
.section-head .eyebrow { color: var(--accent); margin-bottom: 8px; }
.section-lede { margin-top: 10px; font-size: 17px; color: var(--text-light-secondary); max-width: 68ch; }
.section.dark .section-lede { color: var(--text-dark-secondary); }

/* =========================================================================
   Photography. Added 2026-09-17 with the image set.
   ========================================================================= */

/* ---------- Hero backdrop -------------------------------------------------
   The photograph goes behind the copy as a real <img>, not a CSS background,
   so it gets the avif/webp/jpg ladder from the same <picture> helper as
   everything else -- a background-image would need image-set() and would
   still not do widths.
   The scrim is a hard navy gradient rather than a blanket overlay: the left
   third, where the headline sits, stays near-solid so the type keeps its
   contrast, and the right stays readable as a photograph. */
.hero { position: relative; overflow: hidden; }

/* ---------- The hero's surface: a diagonal ramp, not a flat field ---------
   Todor, 2026-09-18: the area under the menu reads too dark, lift it with a
   diagonal -- and then, when the first attempt put the light on the RIGHT:
   lighter on the LEFT, and the map has stopped reading.

   Both halves of that are one mistake. The map's land is drawn in
   --surface-dark (#111A2E) on the assumption that the surface behind it is
   darker; ramping the right end UP to #16283F made the land darker than its
   own background, which inverts figure and ground and washes the whole map
   out. So the light belongs on the left, over the copy, and the right end
   goes DEEPER than the flat navy it started from -- the map reads better now
   than before any of this.

   Three layers, all in colours the identity already owns -- no new hue enters
   the brand:

     1. a diagonal ramp at 104 degrees: cool slate-blue at the top left where
        the copy is, through navy, to navy-deep at the bottom right under the
        map;
     2. a wide cyan wash in the top-left corner at 10% -- the accent used as
        LIGHT, never as a surface (BRAND.md 3: #22D3EE is not a background
        colour);
     3. the deep cyan at the bottom left at 8%, so the lit corner has a floor
        and the ramp travels from something.

   THE SECTION EDGES STAY HARD. BRAND.md 3 forbids gradients BETWEEN sections
   -- the hard horizontal edge is what echoes the bars in the mark. This one
   lives inside the hero and stops at its boundary, so the edge into the proof
   strip is as sharp as it was.

   Not applied when a photograph is the backdrop: there the image and its
   scrim own the surface, and a gradient underneath would never be seen. */
.hero:not(.has-backdrop) {
  background:
    radial-gradient(900px 520px at 2% -8%, var(--hero-wash), transparent 60%),
    radial-gradient(700px 440px at -4% 104%, var(--hero-floor), transparent 66%),
    linear-gradient(104deg, var(--hero-lit) 0%, var(--hero-mid) 30%, var(--navy) 60%, var(--hero-deep) 100%);
}

/* The engineering-drawing grid, 64px, at ~1.6% -- meant to be felt rather than
   seen: it gives the lit corner a scale and keeps the left half from reading
   as unpainted area. Masked along the SAME diagonal as the ramp, so it has
   faded to nothing well before the map -- the map's own geometry is the only
   grid that side of the hero. */
.hero:not(.has-backdrop)::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(148, 163, 184, .16) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(148, 163, 184, .16) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: .10;
  -webkit-mask-image: linear-gradient(104deg, #000 0%, rgba(0,0,0,.45) 34%, transparent 62%);
          mask-image: linear-gradient(104deg, #000 0%, rgba(0,0,0,.45) 34%, transparent 62%);
}
.hero > .container { position: relative; z-index: 1; }

/* Stacked, the hero is map ON TOP and copy below (column-reverse), so the
   left-to-right diagonal would put the light exactly where the map is again.
   Below the breakpoint the ramp runs top to bottom instead: darkest under the
   map, lifting towards the copy and the buttons. */
@media (max-width: 800px) {
  .hero:not(.has-backdrop) {
    background:
      radial-gradient(760px 420px at -10% 100%, var(--hero-wash), transparent 64%),
      linear-gradient(186deg, var(--hero-deep) 0%, var(--navy) 44%, var(--hero-lit) 100%);
  }
  .hero:not(.has-backdrop)::before {
    -webkit-mask-image: linear-gradient(0deg, #000 0%, rgba(0,0,0,.4) 40%, transparent 70%);
            mask-image: linear-gradient(0deg, #000 0%, rgba(0,0,0,.4) 40%, transparent 70%);
  }
}
.hero-backdrop { position: absolute; inset: 0; z-index: 0; }
/* <picture> is display:inline and is NOT what renders -- the <img> inside it is. A
   height set on the <picture> constrains nothing, so the image draws at its natural
   size and everything after it lands on top. Make the wrapper a block and size the
   img. This is the single most likely mistake with <picture>, and it looks like a
   layout bug rather than a selector bug. */
picture { display: block; }
.hero-backdrop picture, .hero-backdrop picture img, .hero-backdrop > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-backdrop::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--navy) 0%, rgba(11,18,32,.94) 38%, rgba(11,18,32,.72) 70%, rgba(11,18,32,.55) 100%);
}
.hero.has-backdrop .container { position: relative; z-index: 1; }
/* What the backdrop is, in text: the scrim would hide a mark in the photo (2026-11-13). On a
   backing of its own, as the bottom right is where the photo shows through the most. */
.hero-photo-note { position: absolute; right: 24px; bottom: 14px; z-index: 2; margin: 0; padding: 3px 8px;
  border-radius: var(--radius-sm); background: rgba(11,18,32,.85);
  font-family: var(--font-mono); font-size: 11px; line-height: 1.4; color: var(--text-dark-nav); }
/* On a phone it flows after the copy instead of floating in the padding, where a wrapped line
   would cover the last button. */
@media (max-width: 800px) { .hero-photo-note { position: relative; right: auto; bottom: auto; width: fit-content;
  max-width: calc(100% - 32px); margin: -38px 16px 10px auto; } }
/* Under our own photos: they are real and not AI-generated (Todor, 2026-11-13). */
.photo-note { font-family: var(--font-mono); font-size: 11px; line-height: 1.5; color: var(--text-light-secondary); margin: 8px 0 0; }
.section.dark .photo-note { color: var(--text-dark-secondary); }
.hero.has-backdrop .hero-mark { filter: drop-shadow(0 12px 40px rgba(0,0,0,.55)); }

/* Procedural grain over the dark hero. 284 bytes, inline, no raster file. */
.grain::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  opacity: .5; mix-blend-mode: overlay;
  background-image: var(--grain-url); background-size: 180px 180px;
}

/* ---------- Full-bleed media band ----------------------------------------
   A photograph edge to edge between two sections. It carries no copy: its job
   is to break the rhythm and to be the only place on the page where the
   hardware is simply shown. */
/* A fixed shape since the photos became our own (2026-11-13): the mark burned into the top
   right of each crop must not be cut off, so the band is 3:1, its own taller 3:2 crop below
   800 px (components/picture, $narrow), and over 1560 px wide the extra is taken from the
   bottom and the left. The figure's default margin is gone: the band is edge to edge. */
.media-band { position: relative; display: block; line-height: 0; background: var(--navy); margin: 0; }
.media-band picture img, .media-band > img { width: 100%; height: auto; aspect-ratio: 3 / 1; max-height: 520px; object-fit: cover; object-position: 100% 0; display: block; }
@media (max-width: 800px) { .media-band picture img, .media-band > img { aspect-ratio: 3 / 2; max-height: none; } }
.media-band.tall picture img, .media-band.tall > img { height: clamp(300px, 46vw, 560px); }
.media-band figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 0;
  background: linear-gradient(0deg, rgba(7,13,25,.86), transparent);
}
.media-band figcaption .container { line-height: var(--lh-body); }
.media-band figcaption p {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-dark-nav); margin: 0;
}

/* ---------- Cards with a picture ------------------------------------------ */
.card-pic { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
/* 2:1 rather than 180 px high (2026-11-13): with a fixed height the crop changed with the card's
   width and cut off the mark in the corner of our photos. */
.card-pic > picture img, .card-pic > img { width: 100%; height: auto; aspect-ratio: 2 / 1; object-fit: cover; display: block; flex: none; }
.card-pic.contain > picture img, .card-pic.contain > img { object-fit: contain; background: var(--surface-light-alt); padding: 14px; }
.card-pic .card-body { padding: 20px 22px 22px; display: flex; flex-direction: column; gap: 8px; }
.card-pic h3 { font-size: 17px; font-weight: 600; }
.card-pic p { font-size: 15px; color: var(--text-light-secondary); }

@media (max-width: 800px) {
  .hero-backdrop::after {
    background: linear-gradient(180deg, rgba(11,18,32,.82) 0%, rgba(11,18,32,.95) 55%, var(--navy) 100%);
  }
}

/* =========================================================================
   Server configurator. Three columns over a sticky summary bar.
   Every control is an <a>, because every state of this page is a URL --
   which is what lets it work with no JavaScript, keeps the strict CSP
   intact, and makes a configuration shareable.
   ========================================================================= */
.cfg { display: grid; grid-template-columns: 1fr 1.25fr 1fr; gap: 28px; align-items: start; }
.cfg-col { display: flex; flex-direction: column; gap: 10px; }
/* Descendant, not child: the tier headings sit inside .cfg-group, one level down, and
   with the child combinator they fell through to the section's 36px h2. */
.cfg-col h2 {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500; margin-bottom: 2px;
}
.cfg-group + .cfg-group { margin-top: var(--space-6); }

/* An option. Selected is a border and a tinted surface, never colour alone. */
.opt {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 13px 15px; border: 1px solid var(--border-light); border-radius: var(--radius-md);
  background: var(--surface-light); color: var(--text-light-primary); text-decoration: none;
  transition: border-color .15s cubic-bezier(.4,0,.2,1), background-color .15s cubic-bezier(.4,0,.2,1);
}
.opt:hover { border-color: var(--text-light-muted); text-decoration: none; }
.opt[aria-current="true"] {
  border-color: var(--cyan-deep); background: #F2FBFD;
  box-shadow: inset 0 0 0 1px var(--cyan-deep);
}
.opt-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.opt-name { font-weight: 500; font-size: 15px; }
.opt-meta { font-size: 13px; color: var(--text-light-secondary); }
.opt-meta .mono { font-family: var(--font-mono); font-size: 12px; }
.opt-price { font-size: 14px; font-weight: 500; color: var(--cyan-deep); white-space: nowrap; }
.opt-price.muted { color: var(--text-light-muted); font-weight: 400; }
.opt-stock { font-size: 12px; color: var(--text-light-muted); font-family: var(--font-mono); }

/* The price bar. FIXED, not sticky: Todor asked for a bar that sits at the bottom and
   stays there however the page is scrolled, as datapacket's does. Sticky released it as
   soon as its own place in the flow came up -- which on a long configurator is exactly
   when the visitor is still choosing. Fixed means it never occupies space, so the page
   reserves the room instead (.page-configure below), or the footer's last line ends up
   underneath it. */
.cfg-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: var(--navy); color: var(--text-dark-primary);
  border-top: 1px solid var(--border-dark);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, .35);
}
/* Room for the fixed bar, and the same room for #anchor scrolling, so a link into the
   page does not land behind it. */
.page-configure { padding-bottom: 96px; scroll-padding-bottom: 104px; }
@media (max-width: 700px) { .page-configure { padding-bottom: 164px; scroll-padding-bottom: 172px; } }
/* The development palette switcher shares this corner; lift it clear of the bar. */
.page-configure .palette-switcher, .page-configure .palette-fab { bottom: 104px; }
@media (max-width: 700px) { .page-configure .palette-switcher, .page-configure .palette-fab { bottom: 172px; } }

/* ---- A term with a definition on hover -------------------------------------
   No JavaScript: hover for a mouse, tabindex for a keyboard, focus for a tap.
   The bubble is hidden with opacity rather than visibility or display, so it
   stays in the accessibility tree and aria-describedby still reads it out. */
.cfg-note { margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--text-light-secondary); }
.tip { position: relative; }
.tip-term {
  border-bottom: 1px dashed var(--text-light-muted); cursor: help;
  color: var(--text-light-primary); font-weight: 500;
}
.tip-term:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 2px; border-radius: 2px; }
.tip-bubble {
  position: absolute; left: 0; bottom: calc(100% + 9px); z-index: 20;
  width: max-content; max-width: 280px; padding: 10px 12px;
  border-radius: var(--radius-md); background: var(--navy-deep); color: var(--text-dark-primary);
  border: 1px solid var(--border-dark); box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  font-size: 12.5px; line-height: 1.5; font-weight: 400;
  opacity: 0; pointer-events: none; transition: opacity .12s linear;
}
/* The little nose, drawn with a rotated square rather than a border triangle so
   it takes the bubble's own border and background. */
.tip-bubble::after {
  content: ""; position: absolute; left: 18px; bottom: -5px; width: 8px; height: 8px;
  background: var(--navy-deep); border-right: 1px solid var(--border-dark);
  border-bottom: 1px solid var(--border-dark); transform: rotate(45deg);
}
/* :focus-within rather than a sibling selector, and plain :focus rather than
   :focus-visible -- the bubble is a SIBLING of the term, and a programmatic or
   touch focus does not match :focus-visible in Chrome, so the first version of
   this rule showed the tooltip to a mouse and to nobody else. */
.tip:hover .tip-bubble, .tip:focus-within .tip-bubble { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .tip-bubble { transition: none; } }
/* On a phone the bubble hangs from the whole note, not from the term. From the term
   it started wherever the term fell in the line and ran past the screen's edge, and
   as it is only transparent while hidden, it made the page wider than the screen on
   step one and the fixed price bar with it (2026-11-11). The nose would point at the
   wrong word from there, so it goes. */
@media (max-width: 520px) {
  .cfg-note { position: relative; }
  .tip { position: static; }
  .tip-bubble { max-width: 100%; }
  .tip-bubble::after { display: none; }
}

/* ---- The billing period ----------------------------------------------------
   First control on the first step and full width, because it multiplies every
   price below it. Same card language and heading as the image grid, so the two
   steps open the same way. It sat in a tinted panel with a gradient, and every
   card said only "-5% discount" (Todor, 2026-11-11: ugly, and no reason to pay
   ahead). Now each card carries what that period costs for this build and what
   it saves, and the deepest discount is marked. */
.cfg-term { margin-bottom: var(--space-7); }
.cfg-term h2 {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500; margin-bottom: 12px;
}
.term-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 900px) { .term-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.term-card {
  position: relative; display: flex; flex-direction: column; gap: 6px; padding: 16px 18px 15px;
  border: 1px solid var(--border-light); border-radius: var(--radius-md);
  background: var(--surface-light); color: var(--text-light-primary); text-decoration: none;
  transition: border-color .15s cubic-bezier(.4,0,.2,1), background-color .15s cubic-bezier(.4,0,.2,1);
}
.term-card:hover { border-color: var(--text-light-muted); text-decoration: none; }
.term-card:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 2px; }
.term-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 22px; }
.term-head b { font-size: 15px; font-weight: 600; }
.term-badge {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 7px; border-radius: var(--radius-sm); background: var(--cyan-deep); color: #fff; white-space: nowrap;
}
.term-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 8px; font-size: 24px; font-weight: 600; line-height: 1.2; letter-spacing: -0.01em; }
.term-price s { font-size: 15px; font-weight: 400; color: var(--text-light-muted); letter-spacing: 0; }
.term-price small { font-size: 14px; font-weight: 400; color: var(--text-light-secondary); letter-spacing: 0; margin-left: -6px; }
.term-save { font-size: 14px; font-weight: 600; color: var(--cyan-deep); }
.term-save.none { font-weight: 400; color: var(--text-light-muted); }
.term-meta { font-size: 13px; color: var(--text-light-secondary); }
.term-card.is-best { border-color: color-mix(in srgb, var(--cyan-deep) 45%, var(--border-light)); }
.term-card[aria-current="true"] {
  border-color: var(--cyan-deep); background: #F2FBFD; box-shadow: inset 0 0 0 1px var(--cyan-deep);
}
/* One period to a row on a phone: two to a row left each card too narrow for its
   price, which broke over three lines. */
@media (max-width: 560px) {
  .term-grid { grid-template-columns: 1fr; gap: 10px; }
  .term-card { padding: 13px 16px 12px; gap: 4px; }
  .term-price { font-size: 22px; }
}
/* The monthly beside the period total: the number to compare with, not the one paid. */
.cfg-per-month { font-family: var(--font-mono); font-size: 13px; color: var(--text-dark-secondary); }

/* ---- The closing block on step two: how many, and anything to tell us ------ */
.cfg-order {
  display: grid; grid-template-columns: minmax(220px, 1fr) 2fr; gap: 28px;
  margin-top: var(--space-7); padding-top: var(--space-6);
  border-top: 1px solid var(--border-light);
}
.cfg-order h2 {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500; margin-bottom: 12px;
}
.cfg-order select { max-width: 260px; }
.cfg-order textarea {
  font: inherit; font-size: 15px; line-height: 1.5; color: var(--text-light-primary);
  width: 100%; padding: 12px 14px; min-height: 108px; resize: vertical;
  background: var(--surface-light); border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
}
/* The server's name beside the note on a ready server's page (2026-11-12): the same box. */
.cfg-order input[type="text"] {
  font: inherit; font-size: 15px; color: var(--text-light-primary); width: 100%; padding: 11px 14px;
  background: var(--surface-light); border: 1px solid var(--border-light); border-radius: var(--radius-md);
}
.cfg-order textarea:focus-visible, .cfg-order input[type="text"]:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 1px; border-color: var(--cyan-deep); }
.cfg-order textarea::placeholder, .cfg-order input[type="text"]::placeholder { color: var(--text-light-muted); }
.cfg-order .hint { display: block; margin-top: 6px; font-size: 13px; color: var(--text-light-secondary); }
@media (max-width: 800px) { .cfg-order { grid-template-columns: 1fr; gap: 22px; } }

/* ---- The operating-system grid ---------------------------------------------
   Cards across the full width of the configurator, above the columns: a mark,
   the name, and a dropdown of releases in every card (2026-11-11, on Todor's
   reference; it was a select under the chosen card only). The name is the link,
   and its ::after is stretched over the card, so a click anywhere but the select
   chooses the image; the select's form sits above that layer. */
.cfg-os { margin-bottom: var(--space-7); }
.cfg-os h2 {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500; margin-bottom: 12px;
}
.os-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 1100px) { .os-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 800px)  { .os-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } }
.os-card {
  position: relative; display: flex; flex-direction: column; gap: 14px; min-width: 0; padding: 16px;
  border: 1px solid var(--border-light); border-radius: var(--radius-md);
  background: var(--surface-light); color: var(--text-light-primary);
  transition: border-color .15s cubic-bezier(.4,0,.2,1), background-color .15s cubic-bezier(.4,0,.2,1);
}
.os-card:hover { border-color: var(--text-light-muted); }
.os-card.is-chosen {
  border-color: var(--cyan-deep); background: #F2FBFD; box-shadow: inset 0 0 0 1px var(--cyan-deep);
}
.os-pick { display: flex; align-items: center; gap: 12px; min-width: 0; color: inherit; text-decoration: none; }
.os-pick:hover { text-decoration: none; }
.os-pick::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.os-pick:focus-visible { outline: none; }
.os-pick:focus-visible::after { outline: 2px solid var(--cyan-deep); outline-offset: 2px; }
.os-pick b { font-size: 17px; font-weight: 600; overflow-wrap: anywhere; }
.os-mark { width: 32px; height: 32px; flex: none; display: block; }
/* Until a vendor's own SVG is dropped into assets/logo/os/, a monogram. Their
   logos are their trademarks, so they are dropped in rather than drawn by us. */
.os-mark.is-monogram {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); background: var(--surface-light-alt);
  color: var(--text-light-secondary); font-family: var(--font-mono); font-size: 14px; font-weight: 500;
}
.os-card.is-chosen .os-mark.is-monogram { background: var(--cyan-deep); color: #fff; }
/* The release, or the line that stands in its place; above the stretched link. */
.os-version, .os-card .os-note { position: relative; z-index: 1; }
.os-version { display: flex; flex-direction: row; align-items: center; gap: 8px; margin: 0; }
.os-version select {
  font: inherit; font-size: 15px; color: var(--text-light-primary); flex: 1 1 auto; width: 100%; min-width: 0;
  padding: 9px 10px; min-height: 42px; cursor: pointer;
  background: var(--surface-light); border: 1px solid var(--border-light); border-radius: var(--radius-sm);
}
.os-version select:hover { border-color: var(--text-light-muted); }
.os-version select:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 1px; }
.os-note { margin: 0; min-height: 42px; display: flex; align-items: center; font-size: 13px; line-height: 1.4; color: var(--text-light-secondary); pointer-events: none; }
.os-hint { margin: 14px 0 0; font-size: 14px; line-height: 1.5; color: var(--text-light-secondary); max-width: 70ch; }
/* On a phone two cards to a row cut the release short ("Rocky Linux 1"), so it is one
   to a row, the name on the left and its dropdown beside it. */
@media (max-width: 560px) {
  .os-grid { grid-template-columns: 1fr; gap: 8px; }
  .os-card { flex-direction: row; align-items: center; gap: 12px; padding: 10px 12px; }
  .os-pick { flex: 1 1 auto; gap: 10px; }
  .os-pick b { font-size: 16px; }
  .os-mark { width: 28px; height: 28px; }
  .os-version, .os-card .os-note { flex: 0 0 54%; }
  .os-card .os-note { min-height: 0; font-size: 12.5px; }
}

/* ---- The IPv4 slider -------------------------------------------------------
   accent-color themes the native track and thumb in one line, which is worth
   more than a hand-built slider: the native control keeps its keyboard
   behaviour, its touch target and its screen-reader semantics for free. */
.cfg-range { gap: 4px; }
.cfg-range output {
  font-size: 15px; font-weight: 500; color: var(--text-light-primary);
  font-variant-numeric: tabular-nums;
}
.cfg-range input[type="range"] {
  width: 100%; margin: 6px 0 2px; accent-color: var(--cyan-deep);
  height: 22px; cursor: pointer;
}
.cfg-range input[type="range"]:focus-visible { outline: 2px solid var(--cyan-deep); outline-offset: 4px; }
.cfg-range-ends {
  display: flex; justify-content: space-between;
  font-family: var(--font-mono); font-size: 11px; color: var(--text-light-muted);
}
/* Visible to a screen reader, not to the eye: the group's own h2 already names
   this control, so a second visible label would repeat it. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- The steps -----------------------------------------------------------
   Links, not a wizard that traps you: every step is a complete URL, so moving
   between them loses nothing. The row of step buttons above the controls went
   on 2026-11-11 (Todor); Back and Continue in the bar are the way between the
   steps. .cfg-step is the hook the script listens on and carries no styling of
   its own, because it sits on those buttons, which must look like buttons. */

/* ---- The add-on form: a select and a checkbox among the option links -------
   Same visual language as an .opt so the column does not split in two. */
.cfg-form { display: flex; flex-direction: column; gap: 12px; }
.cfg-field { display: flex; flex-direction: column; gap: 6px; }
.cfg-field label, .cfg-check b {
  font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--text-light-muted); font-weight: 500;
}
.cfg-field select {
  font: inherit; font-size: 15px; color: var(--text-light-primary);
  min-height: 46px; padding: 11px 13px; width: 100%;
  background: var(--surface-light); border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
}
.cfg-field select:focus-visible, .cfg-check input:focus-visible {
  outline: 2px solid var(--cyan-deep); outline-offset: 1px;
}
.cfg-field .hint, .cfg-check .hint {
  font-size: 13px; line-height: 1.5; color: var(--text-light-secondary);
  font-family: var(--font-sans); letter-spacing: normal; text-transform: none;
}
.cfg-check {
  display: flex; align-items: flex-start; gap: 11px; cursor: pointer;
  padding: 13px 15px; border: 1px solid var(--border-light); border-radius: var(--radius-md);
  background: var(--surface-light);
  transition: border-color .15s cubic-bezier(.4,0,.2,1), background-color .15s cubic-bezier(.4,0,.2,1);
}
.cfg-check:hover { border-color: var(--text-light-muted); }
.cfg-check input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--cyan-deep); flex: none; }
.cfg-check-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cfg-check b { color: var(--text-light-primary); text-transform: none; letter-spacing: normal;
               font-family: var(--font-sans); font-size: 15px; font-weight: 500; }
/* Ticked reads as chosen, the same way a selected option does. */
.cfg-check:has(input:checked) { border-color: var(--cyan-deep); background: #F2FBFD; box-shadow: inset 0 0 0 1px var(--cyan-deep); }
.cfg-apply { align-self: flex-start; }
/* With the script running the controls apply themselves, so the button is noise. */
.cfg-live .cfg-apply { display: none; }

/* While a configuration is being fetched. Only on a page where the script is running --
   without it nothing ever sets aria-busy, and the rule is inert. */
.cfg-live #configure, .cfg-live .cfg-bar { transition: opacity .12s linear; }
.cfg-live #configure[aria-busy="true"] { opacity: .55; }
.cfg-live .cfg-bar[aria-busy="true"] .cfg-price { opacity: .55; }
/* The chosen option should read as chosen the instant it is clicked, not when the
   response lands. :active is the browser's own answer and costs nothing. */
.cfg-live .opt:active { border-color: var(--cyan-deep); }
/* ONE ROW, WHATEVER IS SELECTED. With six choices made the chips wanted 1095px and the
   price with its buttons 686, against a 1200px container -- so the right-hand group
   wrapped underneath and the bar grew to 118px of fixed furniture (Todor, 2026-09-19).
   The price and the button never shrink and never wrap; the chips take what is left and
   scroll sideways in the rare case that they still do not fit, which loses nothing
   because every one of them is also visible in the controls above. */
.cfg-bar .container {
  display: flex; align-items: center; justify-content: space-between; gap: 22px;
  padding-top: 14px; padding-bottom: 14px; flex-wrap: nowrap;
}
.cfg-summary { display: flex; align-items: baseline; gap: 18px; }
.cfg-chips {
  flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; gap: 14px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  /* The fade is the only sign that there is more to the right, since the scrollbar is
     hidden. It costs nothing when the chips are short: the faded strip is then empty
     space, because the group is as wide as the row allows and the chips sit at its left. */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.cfg-chips::-webkit-scrollbar { display: none; }
.cfg-chips > * { flex: none; }
.cfg-total { flex: 0 0 auto; flex-wrap: nowrap; }
/* Back and the next step, as one group; on a phone it is the bar's last row. */
.cfg-actions { display: flex; align-items: center; gap: 12px; }
/* The last step's order button is a form of its own (it posts the build and the note). */
.cfg-go { display: flex; margin: 0; }
.cfg-summary .spec { font-family: var(--font-mono); font-size: 12px; color: var(--text-dark-secondary); }
.cfg-price { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; }
.cfg-price small { font-size: 14px; font-weight: 400; color: var(--text-dark-secondary); }
.cfg-price.unknown { font-size: 16px; font-weight: 500; color: var(--text-dark-secondary); letter-spacing: 0; }
.cfg-delivery { font-size: 13px; color: var(--text-dark-secondary); display: flex; align-items: center; gap: 8px; }
.cfg-delivery::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--cyan); flex: none; }
.cfg-delivery.unknown::before { background: var(--text-dark-muted); }
/* Sold out (Todor, 2026-10-17): a ready server with none in stock, or a build no machine in
   stock can take. Whatever would order it is a disabled button, here, on the plan cards and in
   the list of ready servers, and it has to look it. In the bar the dot goes grey and a line
   under the button says what to change. Where the bar is wide enough the line does not wrap,
   so the bar grows by one line and no more. */
.btn:disabled, .btn:disabled:hover { opacity: .45; cursor: not-allowed; filter: none; }
.cfg-delivery.is-sold-out::before { background: var(--text-dark-muted); }
.cfg-sold-out { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.cfg-sold-out-why { margin: 0; font-size: 12px; line-height: 1.35; color: var(--text-dark-secondary); white-space: nowrap; }
@media (max-width: 1024px) { .cfg-sold-out-why { white-space: normal; max-width: 40ch; } }

@media (max-width: 1024px) { .cfg { grid-template-columns: 1fr 1fr; } .cfg-col:first-child { grid-column: 1 / -1; } }
/* On a phone the bar is allowed to be three rows: there is no width to play with, and
   stacking the total under the chips, and the buttons under the total, is better than a
   horizontal scroll for the price. The total row wraps too: "Continue to image and terms"
   alone is about 230px, and beside a price for twelve months it ran off both edges. */
@media (max-width: 700px)  {
  .cfg { grid-template-columns: 1fr; }
  .cfg-bar .container { flex-wrap: wrap; justify-content: center; text-align: center; row-gap: 10px; padding-top: 12px; padding-bottom: 12px; }
  .cfg-total { flex: 1 1 100%; justify-content: center; flex-wrap: wrap; row-gap: 10px; column-gap: 14px; }
  .cfg-actions { flex: 1 1 100%; justify-content: center; }
  /* The way on (a link, or the order form and its button) is always the group's last. */
  .cfg-actions > :last-child, .cfg-go > [type="submit"] { flex: 1 1 auto; justify-content: center; }
  .cfg-sold-out { align-items: stretch; }
  .cfg-sold-out-why { max-width: none; }
}

/* ---- A ready server on the configurator (2026-09-28) -------------------------------
   Its processor, memory and drives are fixed, so they are a card to read rather than
   options to click, in the first of two columns; the choices that are left sit beside it. */
.cfg.is-package { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); }
.cfg-fixed {
  display: flex; flex-direction: column; gap: 12px; padding: 18px 20px;
  border: 1px solid var(--border-light); border-radius: var(--radius-md); background: var(--surface-light-alt);
}
.cfg-fixed-name { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; color: var(--text-light-primary); }
.cfg-fixed dl { margin: 0; display: flex; flex-direction: column; }
.cfg-fixed dl > div {
  display: flex; justify-content: space-between; gap: 14px; padding: 9px 0;
  border-bottom: 1px solid var(--border-light-soft); font-size: 14px;
}
.cfg-fixed dl > div:last-child { border-bottom: 0; }
.cfg-fixed dt { font-family: var(--font-mono); font-size: 12px; letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-light-muted); }
.cfg-fixed dd { margin: 0; font-weight: 500; text-align: right; color: var(--text-light-primary); }
.cfg-fixed .aside { color: var(--cyan-deep); font-weight: 500; }
/* One with none in stock says so under its delivery, where its disabled Continue points. */
.cfg-fixed-sold-out { margin: 0; font-size: 14px; font-weight: 500; color: var(--text-light-primary); }
.cfg-order.is-note-only { grid-template-columns: minmax(0, 1fr); }
.cfg-gone { margin-bottom: var(--space-6); }
@media (max-width: 1024px) { .cfg.is-package .cfg-col:first-child { grid-column: auto; } }
@media (max-width: 700px)  { .cfg.is-package { grid-template-columns: 1fr; } }

/* ---- A ready server on ONE page (Todor, 2026-11-11) ---------------------------------
   Not a grid of its own: the card beside the network and the addresses, then the operating
   systems and the extras across the width, then the billing period, each with room above it. */
.cfg.cfg-one { display: block; }
.cfg-one-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 28px; align-items: start; margin-bottom: var(--space-7); }
.section h2.cfg-one-heading { font-size: 24px; margin-bottom: 16px; }
.cfg-one-extras { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; align-items: start; margin-bottom: var(--space-7); }
.cfg-one .cfg-term { margin-bottom: 0; }
.cfg-one + .cfg-order { margin-top: var(--space-7); }
@media (max-width: 1024px) { .cfg-one-extras { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .cfg-one-top, .cfg-one-extras { grid-template-columns: 1fr; gap: 22px; } }

/* =========================================================================
   Network map (hero graphic). Cyan on navy; Sofia is the bright origin.
   No inline style attributes anywhere -- the CSP forbids them -- so the
   per-span animation durations are the five .d0-.d4 classes below.
   ========================================================================= */
/* THE MAP BLEEDS TO THE RIGHT EDGE OF THE VIEWPORT, as datapacket's does. Inside the
   1152px content box the copy (640) and the gap (48) leave the map ~490px, and widening
   it there only squeezes the headline onto two lines. The negative margin hands the map
   the container's outer margin and gutter instead -- 144px at 1440 -- so it grows to
   ~640px while the copy keeps every pixel it had. max() keeps the margin at one gutter
   once the viewport is narrower than the container; .hero has overflow hidden, so the
   bleed can never cause horizontal scroll. The 800px breakpoint resets it: stacked, the
   map takes the full content width and needs no margin trick. */
.netmap { width: 100%; max-width: 800px; flex: 1 1 660px;
  margin-right: calc(-1 * max(var(--gutter), (100vw - var(--container)) / 2 + var(--gutter))); }
.netmap svg { display: block; width: 100%; height: auto; overflow: visible; }
.netmap .land { fill: var(--surface-dark); stroke: var(--border-dark); stroke-width: 1; stroke-linejoin: round; }
.netmap .span { fill: none; stroke: var(--cyan); stroke-width: 1.1; opacity: .18; }
.netmap .flow { fill: none; stroke: var(--cyan); stroke-width: 1.8; stroke-linecap: round; opacity: .85;
                stroke-dasharray: 5 26; animation: lsflow 4s linear infinite; }
.netmap .flow.d0 { animation-duration: 3.2s; } .netmap .flow.d1 { animation-duration: 4.1s; }
.netmap .flow.d2 { animation-duration: 5s; }   .netmap .flow.d3 { animation-duration: 5.9s; }
.netmap .flow.d4 { animation-duration: 6.8s; }
@keyframes lsflow { from { stroke-dashoffset: 31; } to { stroke-dashoffset: 0; } }
.netmap .node text { font-family: var(--font-mono); font-size: 12.5px; fill: var(--text-dark-primary); }
.netmap .node text.sub { font-size: 10px; fill: var(--text-dark-muted); letter-spacing: .02em; }
.netmap .node .dot { fill: var(--text-dark-nav); }
.netmap .node .halo { fill: none; stroke: var(--text-dark-nav); stroke-width: 1; opacity: 0; }
.netmap .node.cluster .dot { fill: var(--ivory); }
.netmap .node.cluster .halo { stroke: var(--cyan); opacity: .25; }
.netmap .node.origin .dot { fill: var(--cyan); }
.netmap .node.origin text { fill: var(--cyan); font-weight: 500; }
.netmap .node.origin .halo { stroke: var(--cyan); opacity: .45; transform-box: fill-box; transform-origin: center;
                             animation: lspulse 2.8s ease-in-out infinite; }
@keyframes lspulse { 0%, 100% { opacity: .45; transform: scale(1); } 50% { opacity: .05; transform: scale(1.45); } }
.netmap-legend { margin: 10px 0 0; font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .04em;
                 color: var(--text-dark-muted); display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
/* The legend is as wide as the bleeding map, so without this its last word touches the
   edge of the viewport; the padding gives it the gutter back. */
.netmap-legend { padding-right: var(--gutter); }
.netmap-legend .i { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.netmap-legend .m { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; }
.netmap-legend .o { background: var(--cyan); } .netmap-legend .c { background: var(--ivory); }
.netmap-legend .e { background: var(--text-dark-nav); }
.netmap-legend .f { width: 18px; height: 2px; border-radius: 0; background: var(--cyan); opacity: .7; }
@media (prefers-reduced-motion: reduce) {
  .netmap .flow { animation: none; stroke-dasharray: none; opacity: .4; }
  .netmap .node.origin .halo { animation: none; }
}
@media (max-width: 800px) { .netmap { max-width: none; flex-basis: auto; margin-right: 0; } .netmap-legend { padding-right: 0; } .netmap .node text.sub { display: none; } }

/* Internet-exchange layer on the map: hollow cyan rings, one per city, sized by how many
   exchanges sit there. At a PoP the ring wraps the node instead of adding a second dot. */
.netmap .ix .ring { fill: none; stroke: var(--cyan); stroke-width: 1.2; opacity: .55; stroke-dasharray: 2 3; }
.netmap .ix.at-pop .ring { stroke-dasharray: none; opacity: .3; }
.netmap .ix .core { fill: var(--cyan); opacity: .9; }
.netmap .ix text { font-family: var(--font-mono); font-size: 10.5px; fill: var(--text-dark-secondary); }
.netmap-legend .x { background: transparent; border: 1.5px dashed var(--cyan); box-sizing: border-box; }
@media (max-width: 800px) { .netmap .ix text { display: none; } }

/* =========================================================================
   Added 2026-09-18 with the offers, the SLA, the reseller programme and
   /why-sofia. Same vocabulary as everything above.
   ========================================================================= */

/* ---------- Offer ribbon above the header ---------------------------------
   Deep cyan on navy would fail contrast for 13px text, so the strip is the
   on-dark cyan as BACKGROUND with navy text: 12.6:1. One line; on a phone the
   detail drops and the link stays. */
.ribbon { background: var(--cyan); color: var(--navy); }
.ribbon .container { min-height: 38px; display: flex; align-items: center; position: relative; padding-right: 44px; }
/* The strip's X (2026-11-11): shown by site.js, which also hides a strip this browser closed,
   before the page is drawn. */
.ribbon-x { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; justify-content: center;
            width: 30px; height: 30px; padding: 0; border: 0; border-radius: var(--radius-md); background: none; color: var(--navy); opacity: 0.7; cursor: pointer; }
.ribbon-x[hidden] { display: none; }
.ribbon-x:hover { opacity: 1; background: rgba(11, 18, 32, 0.08); }
html[data-ribbon-hide] .ribbon { display: none; }
.ribbon p { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; font-size: 14px; line-height: 1.3; padding: 8px 0; }
.ribbon strong { font-weight: 600; }
.ribbon .detail { opacity: .8; }
.ribbon a { font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.ribbon a:hover { opacity: .8; }
@media (max-width: 800px) { .ribbon .detail { display: none; } }

/* ---------- Two-column grid, missing until now ---------------------------- */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
@media (max-width: 800px) { .grid-2 { grid-template-columns: 1fr; } }

/* ---------- A padded card, for tables inside cards ------------------------
   The earlier pages set this padding inline; a class means the client area's
   CSP (style-src 'self') will not strip it when the public site gets the same
   policy at launch. */
.card-pad { padding: 22px 24px; }
.card-narrow { max-width: 720px; }

/* ---------- What was still set inline, for the site's CSP (2026-11-12) ----
   /network, /about and /ddos-protection set these in style attributes, the
   last ones on the public site. With them here, style-src 'self' holds. */
.spacer-36 { height: 36px; }
.spacer-40 { height: 40px; }
.block-title { font-size: 20px; font-weight: 600; margin-bottom: 10px; }
.section-lede.tight { margin: 0 0 16px; }
.aside-line { margin-top: 16px; }
.card-pad-24 { padding: 24px; }
.tier-title { font-size: 19px; font-weight: 600; margin-bottom: 14px; }

/* ---------- Tables of facts in a grid, one card per subject ----------------
   /datacenter's parameters (2026-11-11): three across, two on a tablet, one on a
   phone, so from a 360px phone up a table is never narrower than about 260px. */
.spec-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; align-items: start; }
.spec-grid .spec-table th { width: 42%; }
@media (max-width: 1100px) { .spec-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .spec-grid { grid-template-columns: 1fr; gap: 16px; } }

/* ---------- Card extras: eyebrow, check list, fact line ------------------- */
.dc-card .eyebrow { color: var(--cyan-deep); font-size: 11px; margin-bottom: 2px; }
.dc-card .checks { margin-top: 6px; }
.dc-card .checks li { font-size: 14px; }
.dc-card .fact { margin-top: auto; padding-top: 12px; font-family: var(--font-mono); font-size: 12px;
                 line-height: 1.5; color: var(--text-light-muted); border-top: 1px solid var(--border-light-soft); }
.section.dark .dc-card { background: var(--surface-dark); border-color: var(--border-dark); }
.section.dark .dc-card h3 { color: var(--text-dark-primary); }
.section.dark .dc-card p { color: var(--text-dark-secondary); }
.section.dark .dc-card .fact { color: var(--text-dark-muted); border-color: var(--border-dark-soft); }

/* ---------- The two promises --------------------------------------------- */
.promise { padding: 28px 30px; display: flex; flex-direction: column; gap: 10px; }
.promise .eyebrow { color: var(--cyan-deep); }
.promise h3 { font-size: 24px; font-weight: 600; letter-spacing: -0.015em; }
.promise p { font-size: 15px; color: var(--text-light-secondary); }
.promise a.aside { color: var(--cyan-deep); font-weight: 500; font-size: 15px; }

/* ---------- Compliance badges -------------------------------------------- */
.badges { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px; }
.badge-card { display: flex; gap: 14px; align-items: flex-start; padding: 18px 18px 18px 16px;
              background: var(--surface-light); border: 1px solid var(--border-light); border-radius: var(--radius-lg); }
.badge-card svg { width: 36px; height: 36px; flex: none; color: var(--cyan-deep); }
.badge-card b { display: block; font-size: 15px; font-weight: 600; line-height: 1.25; }
.badge-card span { display: block; margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--text-light-secondary); }
.section.dark .badge-card { background: var(--surface-dark); border-color: var(--border-dark); }
.section.dark .badge-card svg { color: var(--cyan); }
.section.dark .badge-card b { color: var(--text-dark-primary); }
.section.dark .badge-card span { color: var(--text-dark-secondary); }
@media (max-width: 1024px) { .badges { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .badges { grid-template-columns: 1fr; } }

/* ---------- Multi-column data table --------------------------------------
   Shares the spec-table's hairlines and type; adds a mono header row and a
   right-aligned figure column. */
.data-table { width: 100%; border-collapse: collapse; }
.data-table caption { text-align: left; font-family: var(--font-mono); font-size: var(--fs-caption);
                      letter-spacing: var(--track-caps); text-transform: uppercase;
                      color: var(--text-light-muted); padding-bottom: 10px; }
.data-table th, .data-table td { text-align: left; padding: 11px 14px 11px 0; border-bottom: 1px solid var(--border-light-soft);
                                 font-size: 15px; vertical-align: top; }
.data-table thead th { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
                       text-transform: uppercase; color: var(--text-light-muted); font-weight: 500;
                       border-bottom: 1px solid var(--border-light); }
.data-table td { color: var(--text-light-primary); }
.data-table td:first-child { font-weight: 500; }
.data-table .num { text-align: right; padding-right: 0; font-variant-numeric: tabular-nums; }
.data-table .mono { font-family: var(--font-mono); font-size: 14px; }
.data-table tr:last-child td { border-bottom: 0; }
.section.dark .data-table td { color: var(--text-dark-primary); border-color: var(--border-dark-soft); }
.section.dark .data-table thead th { color: var(--text-dark-muted); border-color: var(--border-dark); }
@media (max-width: 640px) { .data-table th, .data-table td { font-size: 14px; padding-right: 10px; } }

/* ---------- Forms ---------------------------------------------------------
   One form on the public site today (the reseller request). Plain controls,
   44px tall, the focus ring in the accent so it is visible on white. */
.form { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 22px; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field.wide { grid-column: 1 / -1; }
.field label { font-size: 14px; font-weight: 500; color: var(--text-light-primary); }
.field label small { font-weight: 400; color: var(--text-light-muted); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 15px; line-height: 1.4; color: var(--text-light-primary);
  padding: 11px 13px; min-height: 46px; background: var(--surface-light);
  border: 1px solid var(--border-light); border-radius: var(--radius-md); width: 100%;
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { outline: 2px solid var(--cyan-deep); outline-offset: 1px; border-color: var(--cyan-deep); }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: #B42318; box-shadow: inset 0 0 0 1px #B42318; }
.field .hint { font-size: 13px; color: var(--text-light-muted); }
.form-actions { grid-column: 1 / -1; display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.form-actions .note { font-size: 13px; color: var(--text-light-muted); max-width: 52ch; }
.form-msg { grid-column: 1 / -1; padding: 14px 16px; border-radius: var(--radius-md); font-size: 15px; }
.form-msg.error { background: #FEF3F2; color: #912018; border: 1px solid #FECDCA; }
.form-msg.ok { background: #ECFDF3; color: #085D3A; border: 1px solid #ABEFC6; }
/* The decoy field: off-canvas, never display:none -- some bots skip hidden inputs
   and fill only what is rendered. */
.hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }
@media (max-width: 700px) { .form { grid-template-columns: 1fr; } }

/* ---------- Configurator: commercial options ------------------------------ */
.opt .opt-tag { font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
                color: var(--cyan-deep); }
.cfg-summary .addon { font-size: 13px; color: var(--cyan); font-family: var(--font-mono); }

/* ---------- Why Sofia, short form: five numbered claims in one row -------- */
.claims.five { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 24px; }
.claims.five h3 { font-size: 16px; }
.claims.five p { font-size: 14px; }
@media (max-width: 1024px) { .claims.five { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .claims.five { grid-template-columns: 1fr; } }

/* An <h1> that must look like the section's h2 -- see components/section.php $level. */
.section h1.as-h2 { font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.015em; }
.section.dark h1.as-h2 { color: var(--text-dark-primary); }
/* The configurator's tier labels are h3 now; same look as the column headings. */
.cfg-col h3 { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
              text-transform: uppercase; color: var(--text-light-muted); font-weight: 500; margin-bottom: 2px; }

/* ---------- The shared 404 (views/pages/404.php) --------------------------
   A shared-layer page whose .wrap column this theme never styled, so "Page not found"
   sat against the left edge of the window with its button as plain text (found
   2026-09-22). Dark, like the header and footer around it. */
.wrap { max-width: var(--container); margin: 0 auto; padding: var(--space-8) var(--gutter);
        display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.wrap .eyebrow { color: var(--accent); }
.wrap h1 { font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.015em; }
.wrap p { color: var(--text-dark-secondary); }
.wrap .btn { margin-top: 10px; }

/* ---------- Palette switcher (development only) ---------------------------
   Renders only while content.php has 'palette_switcher' => true. Deliberately
   plain and deliberately in the corner: it is a control for us, not a feature
   of the site, and it should look like one.

   Collapsed by default to a swatch. The swatch is not a generic icon: its
   plate is --navy and its dot is --cyan, so it shows the scheme currently in
   force and changes with it. */
.palette-fab {
  position: fixed; left: 12px; bottom: 12px; z-index: 50;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-md);
  background: rgba(3, 6, 12, .94); border: 1px solid var(--border-dark);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .5);
}
.palette-fab:hover { border-color: var(--text-dark-muted); }
.palette-fab:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.palette-fab svg { width: 22px; height: 22px; display: block; }
.palette-fab .plate { fill: var(--navy); stroke: var(--border-dark); stroke-width: 1.5; }
.palette-fab .dot { fill: var(--cyan); }

.pal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 2px 2px; }
.pal-title { color: var(--text-dark-muted); text-transform: uppercase; }
.pal-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-right: -2px; border-radius: var(--radius-sm);
  color: var(--text-dark-nav);
}
.pal-close:hover { color: var(--text-dark-primary); background: var(--border-dark-soft); }
.pal-close:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.pal-close svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }

.palette-switcher {
  position: fixed; left: 12px; bottom: 12px; z-index: 50;
  display: flex; flex-direction: column; gap: 4px;
  padding: 7px 9px; border-radius: var(--radius-md);
  background: rgba(3, 6, 12, .94); border: 1px solid var(--border-dark);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .5);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .04em;
  max-width: calc(100vw - 24px);
}
.palette-switcher .pal-row { display: flex; align-items: center; flex-wrap: wrap; gap: 3px; }
.palette-switcher .pal-label {
  color: var(--text-dark-muted); text-transform: uppercase;
  width: 62px; flex: none; padding-left: 2px;
}
.palette-switcher a {
  padding: 5px 9px; border-radius: var(--radius-sm);
  color: var(--text-dark-nav); border: 1px solid transparent; white-space: nowrap;
}
.palette-switcher a:hover { border-color: var(--border-dark); color: var(--text-dark-primary); }
.palette-switcher a[aria-current="true"] { background: var(--cyan); color: var(--navy); font-weight: 500; }
@media (max-width: 800px) { .palette-switcher { left: 8px; right: 8px; bottom: 8px; justify-content: center; } }

/* =========================================================================
   Added 2026-09-23 with the partner program, colocation and the custom
   server request. Todor: long text and long tables are hard to read, so the
   pages are laid out "like a chessboard, with photos", with icons, ladders
   and steps where a table or a paragraph used to be, and enough on each to
   decide on. Same tokens and the same light/dark rules as everything above.
   ========================================================================= */

/* The header nav's fitting rules (no label wraps, tighter gaps, the menu below 1200px) are in
   chrome.css since 2026-11-11, when the client area's header took the same nav. */

.ico { width: 24px; height: 24px; display: block; }
.stack-lg { display: flex; flex-direction: column; gap: 28px; }
.stack-xl { display: flex; flex-direction: column; gap: var(--space-8); }
.panel-dark { padding: 34px 30px; border: 1px solid var(--border-dark); border-radius: var(--radius-lg);
              background: linear-gradient(180deg, rgba(17, 26, 46, .75), rgba(17, 26, 46, .35)); }
@media (max-width: 520px) { .panel-dark { padding: 24px 18px; } }
.ladders .card-pad { padding: 26px 26px 22px; }
/* Four discount steps beside five bonus steps: the second card gets the wider share. */
.grid-2.ladders { grid-template-columns: minmax(0, 4fr) minmax(0, 5fr); }
@media (max-width: 1024px) { .grid-2.ladders { grid-template-columns: 1fr; } }
.grid-5 { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 1024px) { .grid-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .grid-5 { grid-template-columns: 1fr; } }
@media (max-width: 800px)  { .grid-4.icon-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px)  { .grid-4.icon-grid { grid-template-columns: 1fr; } }

/* ---------- Icon grid: an icon, a title, a line or two ------------------- */
.icon-grid { gap: 32px 26px; }
.ig-item { display: flex; flex-direction: column; gap: 8px; }
.ig-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; margin-bottom: 6px; border-radius: var(--radius-md);
  color: var(--accent); background: rgba(12, 141, 161, .09);
  background: color-mix(in srgb, var(--accent) 11%, transparent);
}
.ig-item h3 { font-size: 17px; font-weight: 600; line-height: 1.3; }
.ig-item p { font-size: 15px; color: var(--text-light-secondary); }
.ig-item .aside { font-size: 14px; font-weight: 500; color: var(--accent); }
.section.dark .ig-item p { color: var(--text-dark-secondary); }

/* ---------- Photo rows, alternating sides --------------------------------
   The picture is cropped to one shape for every row, so a page of them reads
   as a pattern rather than a stack of differently sized photographs. */
.zigzag { display: flex; flex-direction: column; gap: var(--space-8); }
.zz-row { display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr); align-items: center; gap: 60px; }
.zz-row.flip { grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); }
.zz-row.flip .zz-media { order: 2; }
.zz-media { position: relative; }
.zz-pic { position: relative; }
.zz-media picture img { width: 100%; aspect-ratio: 16 / 11; object-fit: cover; border-radius: var(--radius-lg); display: block; }
.zz-badge {
  position: absolute; left: 18px; bottom: 18px; width: 54px; height: 54px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-md); background: var(--navy); color: var(--cyan);
  border: 1px solid var(--border-dark); box-shadow: 0 4px 12px rgba(0, 0, 0, .28);
}
.zz-row.flip .zz-badge { left: auto; right: 18px; }
.zz-badge .ico { width: 26px; height: 26px; }
.zz-copy { display: flex; flex-direction: column; gap: 14px; max-width: 540px; }
.zz-copy .eyebrow { color: var(--accent); }
.zz-copy h3 { font-size: 27px; font-weight: 600; line-height: 1.2; letter-spacing: -0.015em; }
.zz-body { font-size: 16px; color: var(--text-light-secondary); }
.zz-copy .checks { margin-top: 4px; }
.zz-fact { font-family: var(--font-mono); font-size: 12px; line-height: 1.5; color: var(--text-light-muted);
           padding-top: 12px; border-top: 1px solid var(--border-light-soft); }
.zz-copy .aside { color: var(--accent); font-weight: 500; }
.section.dark .zz-body { color: var(--text-dark-secondary); }
.section.dark .zz-fact { color: var(--text-dark-muted); border-color: var(--border-dark-soft); }
@media (max-width: 800px) {
  .zigzag { gap: var(--space-7); }
  .zz-row, .zz-row.flip { grid-template-columns: 1fr; gap: 22px; }
  .zz-row.flip .zz-media { order: 0; }
  .zz-copy h3 { font-size: 22px; }
}

/* ---------- Figure cards: the number first ------------------------------- */
.fig-card { padding: 24px 24px 22px; display: flex; flex-direction: column; gap: 8px; }
.fig-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.fig-figure { font-size: 40px; font-weight: 600; line-height: 1; letter-spacing: -0.03em; color: var(--accent); }
.fig-icon { color: var(--text-light-muted); }
.fig-card h3 { font-size: 18px; font-weight: 600; }
.fig-card p { font-size: 15px; color: var(--text-light-secondary); }
.fig-card .fig-fact { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border-light-soft);
                      font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; text-transform: uppercase;
                      color: var(--text-light-muted); }
.section.dark .fig-card { background: var(--surface-dark); border-color: var(--border-dark); }
.section.dark .fig-card h3 { color: var(--text-dark-primary); }
.section.dark .fig-card p { color: var(--text-dark-secondary); }
.section.dark .fig-card .fig-fact { color: var(--text-dark-muted); border-color: var(--border-dark-soft); }
.section.dark .fig-icon { color: var(--text-dark-muted); }

/* ---------- Ladder: tiers as rising steps ---------------------------------
   Wide, the steps are columns that grow; on a phone they become bars that
   grow sideways, with the condition on the left. The last step is filled. */
.ladder { margin: 0; }
.ladder-cap { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
              text-transform: uppercase; color: var(--text-light-muted); margin-bottom: 16px; }
.ladder-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column;
                grid-auto-columns: minmax(0, 1fr); gap: 10px; align-items: end; }
.ladder-step { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ladder-bar {
  display: flex; flex-direction: column; gap: 3px; padding: 14px 14px 12px;
  border-radius: var(--radius-md) var(--radius-md) 0 0; border-top: 3px solid var(--accent);
  background: #E7F4F6; background: color-mix(in srgb, var(--accent) 11%, var(--surface-light));
}
.lv-1 .ladder-bar { min-height: 76px; }  .lv-2 .ladder-bar { min-height: 104px; }
.lv-3 .ladder-bar { min-height: 132px; } .lv-4 .ladder-bar { min-height: 160px; }
.lv-5 .ladder-bar { min-height: 188px; } .lv-6 .ladder-bar { min-height: 216px; }
.ladder-value { font-size: 24px; font-weight: 600; line-height: 1.1; letter-spacing: -0.02em; color: var(--text-light-primary); }
.ladder-note { font-size: 13px; color: var(--text-light-secondary); }
/* A step's name above its value, in the bar (2026-11-11). */
.ladder-tier { font-family: var(--font-mono); font-size: 11px; letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-light-muted); }
.ladder-5 .ladder-bar, .ladder-6 .ladder-bar { padding: 12px 11px 10px; }
.ladder-5 .ladder-value, .ladder-6 .ladder-value { font-size: 20px; }
.ladder-5 .ladder-note, .ladder-6 .ladder-note { font-size: 12px; }
.ladder-step.is-top .ladder-bar { background: var(--accent); }
.ladder-step.is-top .ladder-value, .ladder-step.is-top .ladder-note, .ladder-step.is-top .ladder-tier { color: var(--accent-fg); }
.ladder-label { font-size: 14px; font-weight: 500; color: var(--text-light-body); padding-top: 9px; border-top: 1px solid var(--border-light); }
.ladder-foot { margin-top: 16px; font-size: 14px; color: var(--text-light-secondary); max-width: 62ch; }
@media (max-width: 640px) {
  .ladder-steps { grid-auto-flow: row; gap: 8px; }
  .ladder-step { display: grid; grid-template-columns: 104px minmax(0, 1fr); align-items: center; gap: 12px; }
  .ladder-label { order: -1; padding-top: 0; border-top: 0; font-size: 13px; }
  .ladder .ladder-bar { min-height: 0; border-radius: var(--radius-md); border-top: 0; border-left: 3px solid var(--accent);
                        flex-direction: row; align-items: baseline; flex-wrap: wrap; gap: 2px 10px; padding: 10px 12px; }
  .lv-1 .ladder-bar { width: 55%; } .lv-2 .ladder-bar { width: 64%; } .lv-3 .ladder-bar { width: 73%; }
  .lv-4 .ladder-bar { width: 82%; } .lv-5 .ladder-bar { width: 91%; } .lv-6 .ladder-bar { width: 100%; }
  .ladder-value { font-size: 19px; }
  .ladder-tier { flex-basis: 100%; }   /* the level on its own line in every bar, short or long */
}

/* ---------- Steps along a line ------------------------------------------- */
.steps { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 28px; }
.step { position: relative; display: flex; flex-direction: column; gap: 8px; }
.step-n {
  display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px; margin-bottom: 8px;
  border-radius: 50%; border: 1.5px solid var(--accent); color: var(--accent);
  font-family: var(--font-mono); font-size: 13px; font-weight: 500;
}
.step::before { content: ""; position: absolute; top: 21px; left: 54px; right: -16px; height: 1px; background: var(--border-light); }
.step:last-child::before { display: none; }
.step h3 { font-size: 17px; font-weight: 600; }
.step p { font-size: 15px; color: var(--text-light-secondary); }
.section.dark .step::before { background: var(--border-dark); }
.section.dark .step p { color: var(--text-dark-secondary); }
@media (max-width: 800px) {
  .steps { grid-auto-flow: row; gap: 24px; }
  .step { padding-left: 60px; }
  .step-n { position: absolute; left: 0; top: -4px; margin: 0; }
  .step::before { top: 44px; bottom: -20px; left: 21px; right: auto; width: 1px; height: auto; }
}

/* ---------- Versus: the usual way against ours ----------------------------
   The marks are drawn: a dash for the usual answer, a tick in the accent for
   ours. On a phone every row turns into a small card with both answers, each
   under its column's name. */
.versus-wrap { border: 1px solid var(--border-light); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface-light); }
.versus { width: 100%; border-collapse: collapse; }
.versus caption { text-align: left; padding: 16px 20px 0; font-family: var(--font-mono); font-size: var(--fs-caption);
                  letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-light-muted); }
.versus thead th { text-align: left; padding: 16px 20px; font-family: var(--font-mono); font-size: var(--fs-caption);
                   letter-spacing: var(--track-caps); text-transform: uppercase; font-weight: 500;
                   color: var(--text-light-muted); border-bottom: 1px solid var(--border-light); }
.versus thead th.vs-us { color: var(--accent); }
.versus tbody th { width: 22%; text-align: left; vertical-align: top; padding: 17px 20px; font-size: 15px; font-weight: 600; color: var(--text-light-primary); }
.versus td { position: relative; vertical-align: top; padding: 17px 22px 17px 50px; font-size: 15px; line-height: 1.5; }
.versus td.vs-them { color: var(--text-light-secondary); width: 37%; }
.versus td.vs-us { color: var(--text-light-primary); font-weight: 500; background: #F2FAFB;
                   background: color-mix(in srgb, var(--accent) 6%, var(--surface-light)); }
.versus thead th.vs-us { background: #F2FAFB; background: color-mix(in srgb, var(--accent) 6%, var(--surface-light)); }
.versus td.vs-them::before { content: ""; position: absolute; left: 22px; top: 27px; width: 13px; height: 2px; border-radius: 1px; background: var(--text-light-muted); opacity: .7; }
.versus td.vs-us::before { content: ""; position: absolute; left: 26px; top: 20px; width: 6px; height: 12px; border: solid var(--accent);
                           border-width: 0 2px 2px 0; transform: rotate(45deg); }
.versus tbody tr + tr > * { border-top: 1px solid var(--border-light-soft); }
@media (max-width: 700px) {
  .versus thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .versus, .versus tbody, .versus tr, .versus th, .versus td { display: block; width: auto; }
  .versus tbody th, .versus td.vs-them { width: auto; }
  .versus tbody tr { padding: 16px 18px; }
  .versus tbody th { padding: 0 0 10px; }
  .versus td { display: flex; flex-direction: column-reverse; gap: 3px; padding: 8px 10px 8px 34px; border-radius: var(--radius-sm); }
  .versus td::after { content: attr(data-col); font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em;
                      text-transform: uppercase; font-weight: 500; color: var(--text-light-muted); }
  .versus td.vs-us::after { color: var(--accent); }
  .versus td.vs-them::before { left: 10px; top: 32px; }
  .versus td.vs-us::before { left: 14px; top: 25px; }
  .versus tbody tr + tr > * { border-top: 0; }
  .versus tbody tr + tr { border-top: 1px solid var(--border-light-soft); }
}

/* ---------- Timeline: the same night, told twice ------------------------- */
.timeline { margin: 0; }
.tl-cap { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
          text-transform: uppercase; color: var(--text-light-muted); margin-bottom: 14px; }
.tl-lanes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
.tl-lane { display: flex; flex-direction: column; padding: 24px 26px 22px; border: 1px solid var(--border-light);
           border-radius: var(--radius-lg); background: var(--surface-light); }
.tl-lane.tl-us { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.tl-label { font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
            text-transform: uppercase; font-weight: 500; color: var(--text-light-muted); margin-bottom: 20px; }
.tl-us .tl-label { color: var(--accent); }
.tl-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.tl-steps li { position: relative; display: flex; flex-direction: column; gap: 2px; padding: 0 0 20px 28px; }
.tl-steps li::before { content: ""; position: absolute; left: 0; top: 4px; width: 12px; height: 12px; border-radius: 50%;
                       border: 2px solid var(--text-light-muted); background: var(--surface-light); box-sizing: border-box; }
.tl-steps li::after { content: ""; position: absolute; left: 5.5px; top: 20px; bottom: 2px; width: 1px; background: var(--border-light); }
.tl-steps li:last-child { padding-bottom: 6px; }
.tl-steps li:last-child::after { display: none; }
.tl-us .tl-steps li::before { border-color: var(--accent); }
.tl-us .tl-steps li:last-child::before { background: var(--accent); }
.tl-when { font-family: var(--font-mono); font-size: 13px; font-weight: 500; color: var(--text-light-primary); }
.tl-what { font-size: 15px; color: var(--text-light-secondary); }
.tl-total { margin-top: auto; padding-top: 16px; border-top: 1px solid var(--border-light-soft);
            font-size: 21px; font-weight: 600; letter-spacing: -0.01em; color: var(--text-light-primary); }
.tl-us .tl-total { color: var(--accent); }
@media (max-width: 800px) { .tl-lanes { grid-template-columns: 1fr; } }

/* ---------- Where a partner's network sits in ours ------------------------
   For a dark section. Five columns wide: their side, a link, our border, a
   link, what the border reaches. Stacked on a phone, the links turn upright. */
.asn-flow { display: grid; grid-template-columns: minmax(0, 1fr) 96px minmax(0, 1fr) 96px minmax(0, .9fr); align-items: center; }
.af-col { display: flex; flex-direction: column; gap: 12px; }
.af-node { display: flex; align-items: center; gap: 14px; padding: 15px 16px; border: 1px solid var(--border-dark);
           border-radius: var(--radius-md); background: var(--surface-dark); }
.af-node.is-you { border-color: var(--cyan); }
.af-node.is-optional { border-style: dashed; }
.af-node.is-edge { padding: 24px 18px; border-color: var(--cyan); box-shadow: 0 0 0 5px rgba(34, 211, 238, .07); }
.af-icon { color: var(--cyan); flex: none; }
.af-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.af-text b { font-size: 15px; font-weight: 600; color: var(--text-dark-primary); }
.af-text span { font-size: 13px; line-height: 1.45; color: var(--text-dark-secondary); }
.af-node.is-out { align-items: baseline; gap: 10px; padding: 12px 16px; }
.af-node.is-out b { font-size: 20px; font-weight: 600; color: var(--cyan); white-space: nowrap; }
.af-node.is-out span { font-size: 14px; color: var(--text-dark-secondary); }
.af-link { position: relative; height: 2px; margin: 0 8px; opacity: .8;
           background: repeating-linear-gradient(90deg, var(--cyan) 0 6px, transparent 6px 12px); }
.af-link span { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); white-space: nowrap;
                font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--cyan); }
@media (max-width: 900px) {
  .asn-flow { grid-template-columns: 1fr; }
  .af-link { width: 2px; height: 46px; margin: 8px 0 8px 28px;
             background: repeating-linear-gradient(180deg, var(--cyan) 0 6px, transparent 6px 12px); }
  .af-link span { left: 16px; bottom: auto; top: 50%; transform: translateY(-50%); }
}

/* ---------- The custom server request ------------------------------------
   Seven numbered groups in one form, with what happens next beside it. Each
   group is a fieldset with its own frame, so a long form reads as short steps;
   the fields inside use the same .form grid and .field look as the partner
   application. */
.req-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 36px; align-items: start; }
.req-form { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.req-set { margin: 0; padding: 22px 24px 24px; border: 1px solid var(--border-light); border-radius: var(--radius-lg); background: var(--surface-light); min-width: 0; }
.req-set legend { display: flex; align-items: center; gap: 12px; padding: 0 8px; margin-left: -8px;
                  font-size: 18px; font-weight: 600; color: var(--text-light-primary); }
.req-n { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex: none;
         border-radius: 50%; border: 1.5px solid var(--accent); color: var(--accent);
         font-family: var(--font-mono); font-size: 12px; font-weight: 500; }
.req-set .form { margin-top: 14px; }
.req-hint { margin: 10px 0 0; font-size: 14px; color: var(--text-light-secondary); max-width: 70ch; }
.req-drives { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.req-drive { display: grid; grid-template-columns: 84px minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, .8fr); gap: 12px 16px; align-items: end;
             padding: 14px 16px; border-radius: var(--radius-md); background: var(--surface-light-alt); }
.req-drive-n { margin: 0 0 13px; font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-light-muted); }
.req-drive.is-optional .field label small { display: none; }
.req-checks { display: flex; flex-direction: column; gap: 10px; justify-content: flex-end; min-width: 0; }
.req-checks .cfg-check b { font-size: 14px; }
.req-aside { position: sticky; top: 88px; display: flex; flex-direction: column; gap: 16px; }
.req-next { padding: 22px 22px 20px; }
.req-next h3 { font-size: 17px; font-weight: 600; margin-bottom: 14px; }
.req-next ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.req-next li { display: flex; gap: 12px; align-items: flex-start; font-size: 14px; color: var(--text-light-secondary); }
.req-next li b { display: block; font-size: 15px; font-weight: 600; color: var(--text-light-primary); margin-bottom: 2px; }
.req-brand { display: flex; gap: 12px; align-items: flex-start; padding: 16px 18px; border-radius: var(--radius-lg);
             background: var(--navy); color: var(--text-dark-secondary); }
.req-brand .ico { color: var(--cyan); flex: none; margin-top: 2px; }
.req-brand p { font-size: 14px; line-height: 1.5; }
@media (max-width: 1024px) {
  .req-layout { grid-template-columns: 1fr; }
  .req-aside { position: static; order: -1; }
}
@media (max-width: 700px) {
  .req-set { padding: 18px 16px 20px; }
  .req-drive { grid-template-columns: 1fr; gap: 10px; }
  .req-drive-n { margin: 0; }
}

/* ---------- Tables that are easier to read (Todor, 2026-09-23) ------------
   Every spec table and data table on the site gets rows in alternating tints
   and room on both sides of each cell, so the eye can follow a row across. A
   list of values in a cell (the latency table's cities) becomes chips. */
.spec-table th, .spec-table td { padding: 11px 14px; }
.spec-table tbody tr:nth-child(even) > * { background: var(--surface-light-alt); }
.spec-table tbody tr > :first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.spec-table tbody tr > :last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.spec-table th, .spec-table td, .data-table th, .data-table td { border-bottom: 0; }
.spec-table caption, .data-table caption { padding-left: 14px; }
.data-table th, .data-table td { padding: 12px 14px; }
.data-table thead th { border-bottom: 1px solid var(--border-light); }
.data-table tbody tr:nth-child(even) > td { background: var(--surface-light-alt); }
.data-table .num { padding-right: 14px; }
.section.dark .spec-table tbody tr:nth-child(even) > *,
.section.dark .data-table tbody tr:nth-child(even) > td { background: rgba(148, 163, 184, .06); }
.cell-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.cell-chip { font-family: var(--font-mono); font-size: 12.5px; padding: 4px 9px; border-radius: var(--radius-sm);
             background: var(--surface-light); border: 1px solid var(--border-light); color: var(--text-light-body); white-space: nowrap; }
.section.dark .cell-chip { background: var(--surface-dark); border-color: var(--border-dark); color: var(--text-dark-nav); }

/* =========================================================================
   Added 2026-10-20 with /legal: the General Terms, the refund rules, the
   Acceptable Use Policy and the privacy notice. Running legal text, which
   nothing above renders: h1, h2, h3 and p carry margin 0 and there was no
   prose column. One column of about 76 characters, a clause heading, a
   numbered paragraph, a plain list, and a card for a table or a form.
   ========================================================================= */
.legal { max-width: 76ch; }
.legal h3 { font-size: var(--fs-h3); font-weight: 600; line-height: 1.3; margin-top: var(--space-7); color: var(--text-light-primary); }
.legal h3:first-child { margin-top: 0; }
.legal p { margin-top: 12px; line-height: 1.6; color: var(--text-light-body); }
.legal p .n { font-family: var(--font-mono); font-size: 13px; color: var(--text-light-muted); margin-right: 4px; }
.legal ul { margin: 10px 0 0; padding-left: 22px; line-height: 1.6; color: var(--text-light-body); }
.legal li + li { margin-top: 6px; }
/* A long address or link must not push a phone's column sideways. */
.legal p, .legal li, .legal td { overflow-wrap: anywhere; }
.legal a { color: var(--cyan-deep); font-weight: 500; }
.legal .card { margin-top: 14px; }
.legal .card p { margin-top: 6px; font-size: 15px; }
.legal .card p:first-child { margin-top: 0; }
.legal .card .spec-table th { width: 32%; }
/* The version line: in the dark opening band, and again, in the light, at the top of the
   terms, where a reader quoting them looks for it. */
.legal-version { margin-top: 18px; font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--track-caps);
                 text-transform: uppercase; }
.section.dark p.legal-version { color: var(--text-dark-muted); }
p.legal-version.light { margin: 0 0 var(--space-6); color: var(--text-light-muted); }
.legal-parts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.legal-parts a.pill:hover { border-color: var(--cyan); color: var(--text-dark-primary); }
/* A link into a page lands under the sticky 64px header everywhere on the site. On this
   page the anchors are the point (the registration form links #terms and #privacy), so
   here, and only here, they clear it. */
.page-legal [id] { scroll-margin-top: 84px; }
/* The line under the support FAQ (it was an inline margin; see support.php). */
.faq-foot { margin-top: 32px; }

/* =========================================================================
   Added 2026-10-21 with the guarantee page laid out again (Todor: it looked
   too long and its text hard to read). The five rules as five cards, then
   what is and is not covered side by side; a cross for what is not covered.
   ========================================================================= */
.claims.five.rules { margin-bottom: 24px; }
.claims.five.rules .claim { gap: 6px; }
.cover-lists .card h3 { font-size: 18px; font-weight: 600; margin-bottom: 14px; }
/* The longer list in the wider column, so neither card is left half empty. */
.grid-2.cover-lists { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
@media (max-width: 800px) { .grid-2.cover-lists { grid-template-columns: 1fr; } }
/* Between a phone and a desktop, three cards over two, each row full. */
@media (min-width: 701px) and (max-width: 1024px) {
  .claims.five.rules { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .claims.five.rules .claim { grid-column: span 2; }
  .claims.five.rules .claim:nth-child(n+4) { grid-column: span 3; }
}
/* On a phone the number sits beside the title, so the five fit in about one screen. */
@media (max-width: 700px) {
  .claims.five.rules { gap: 12px; }
  .claims.five.rules .claim { display: grid; grid-template-columns: 30px minmax(0, 1fr); column-gap: 6px; row-gap: 4px; padding: 16px 18px; }
  .claims.five.rules .claim .n { grid-row: 1; padding-top: 4px; }
  .claims.five.rules .claim p { grid-column: 2; }
}
.cover-lists .more { margin-top: 16px; font-size: 15px; }
.cover-lists .more .aside { color: var(--accent); font-weight: 500; }
/* The cross: two strokes drawn like the tick, so it follows the text and costs no request. */
.checks.no li::before, .checks.no li::after {
  content: ""; position: absolute; left: 3px; top: 10px; width: 12px; height: 0;
  border: 0; border-top: 2px solid var(--text-light-muted); transform: rotate(45deg);
}
.checks.no li::after { transform: rotate(-45deg); }

/* Running text that makes an argument (components/prose.php, /why-choose-us, 2026-11-11).
   600px is about 75 characters at 17px; the size is on the paragraphs, so a ch width on
   the column measured the 16px around it and let the lines run to a hundred. The figures
   stand in the other half, and stay in view while the text beside them is read. The
   table that sums the text up follows closer than a new section would. */
.prose { max-width: 600px; }
.prose-wrap.has-facts { display: grid; grid-template-columns: minmax(0, 600px) minmax(0, 1fr); gap: 72px; align-items: start; }
.prose-facts { margin: 0; position: sticky; top: 96px; display: grid; gap: 26px; padding-left: 32px; border-left: 1px solid var(--border-light); }
.prose-facts dt { font-size: 40px; font-weight: 600; line-height: 1; letter-spacing: -0.03em; color: var(--accent); }
.prose-facts dd { margin: 6px 0 0; font-size: 15px; line-height: 1.45; color: var(--text-light-secondary); max-width: 30ch; }
@media (max-width: 900px) {
  .prose-wrap.has-facts { grid-template-columns: 1fr; gap: 32px; }
  .prose-facts { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 20px; padding: 24px 0 0; border-left: 0; border-top: 1px solid var(--border-light); }
  .prose-facts dt { font-size: 32px; }
}
.prose-wrap + .versus-wrap { margin-top: 48px; }
.prose p { font-size: 17px; line-height: 1.65; color: var(--text-light-body); }
.prose p + p { margin-top: 14px; }
.section.dark .prose p { color: var(--text-dark-secondary); }
