/* --- 0. Self-hosted Manrope ----------------------------------------------
   Served from our own domain. Loading fonts from Google would send every
   visitor's IP address to a third country, which is the one thing that
   would force a cookie/consent banner onto an otherwise tracker-free site.
   ------------------------------------------------------------------------ */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url('/assets/fonts/manrope-latin-400-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url('/assets/fonts/manrope-latin-700-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-display: swap;
  font-weight: 800;
  src: url('/assets/fonts/manrope-latin-800-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   shelly.guide — base stylesheet
   Layout v2. Tokens taken from the IHC calculator so guides, tools and the
   site read as one family. One column, cards on a light field, compact hero.
   ========================================================================== */

/* --- 1. Tokens ----------------------------------------------------------- */
:root {
  --sg-navy:     #003C82;
  --sg-midnight: #122A4F;
  --sg-blue:     #4594d1;
  --sg-blue-600: #3a80b6;
  --sg-sky:      #AAE1FA;
  --sg-tint:     #eef6fc;
  --sg-muted:    #5b6b7d;
  --sg-line:     #dbe6ef;
  --sg-shell:    #f2f7fb;
  --sg-page:     #e7eef5;
  --sg-paper:    #ffffff;
  --sg-amber:    #b7791f;
  --sg-amber-bg: #fff8e8;
  --sg-amber-line:#f0d199;

  --sg-r: 14px;
  --sg-r-sm: 10px;
  --sg-shadow: 0 6px 24px rgba(18, 42, 79, .10);
  --sg-shadow-lift: 0 12px 32px rgba(18, 42, 79, .16);

  --sg-font: 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --sg-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --gutter: 20px;
  --wrap: 900px;
  --header-h: 58px;
}
@media (min-width: 900px) { :root { --gutter: 28px; } }

/* --- 2. Base ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 18px);
  background: var(--sg-page);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  background: var(--sg-page);
  color: var(--sg-midnight);
  font-family: var(--sg-font);
  font-size: 16.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
body.is-locked { overflow: hidden; }

h1, h2, h3, h4 { color: var(--sg-midnight); margin: 0 0 .5em; line-height: 1.25; font-weight: 800; letter-spacing: -.012em; }
h1 { font-size: clamp(26px, 4.6vw, 34px); }
h2 { font-size: clamp(21px, 2.6vw, 25px); }
h3 { font-size: 20px; }
h4 { font-size: 15.5px; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
ul, ol { margin: 0 0 1em; padding-left: 1.25em; }
li { margin-bottom: .4em; }
strong { font-weight: 800; color: var(--sg-midnight); }

a { color: var(--sg-navy); text-decoration: none; border-bottom: 1px solid rgba(0,60,130,.28); }
a:hover { color: var(--sg-blue-600); border-bottom-color: currentColor; }
:focus-visible { outline: 2px solid var(--sg-blue); outline-offset: 2px; border-radius: 4px; }

img { max-width: 100%; height: auto; display: block; }
hr { border: 0; border-top: 1px solid var(--sg-line); margin: 2rem 0; }

code {
  font-family: var(--sg-mono); font-size: .88em;
  background: var(--sg-tint); border: 1px solid var(--sg-line);
  border-radius: 5px; padding: .1em .4em; color: var(--sg-navy);
}
pre {
  font-family: var(--sg-mono); font-size: 14px; line-height: 1.55;
  background: var(--sg-midnight); color: #dceaf7;
  border-radius: var(--sg-r-sm); padding: 15px 17px; overflow-x: auto;
}
pre code { background: none; border: 0; color: inherit; padding: 0; }

/* --- Code blocks ---------------------------------------------------------
   Highlighted at build time by tools/code.js; no highlighter reaches the
   reader. The palette is the site's own: sky for keywords, the amber that the
   warning callouts already use for strings, and one blue mixed between
   --sg-blue and --sg-sky for numbers, because the palette has no third cool
   hue. An imported theme would put purple and magenta on a navy page and read
   as though it had wandered in from somewhere else. */
:root {
  --sg-code-dim: rgba(220, 234, 247, .52);
  --sg-code-key: var(--sg-sky);
  --sg-code-str: var(--sg-amber-line);
  --sg-code-num: #8fc7ec;
}
.sg-code { position: relative; margin: 1.1rem 0; }
.sg-code pre { margin: 0; }
/* Only when the button exists — it is added by JS, so a browser without the
   clipboard API gets the tighter block and no dead space. */
.sg-code.has-copy pre { padding-top: 44px; }

.sg-code__copy {
  position: absolute; top: 9px; right: 9px;
  font: 800 11px/1 var(--sg-font); letter-spacing: .1em; text-transform: uppercase;
  color: var(--sg-code-dim); background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .17); border-radius: 7px;
  padding: 8px 12px; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.sg-code__copy:hover { background: rgba(255, 255, 255, .17); color: #fff; }
.sg-code__copy:focus-visible { outline: 2px solid var(--sg-sky); outline-offset: 2px; }
.sg-code__copy.is-done { color: var(--sg-sky); border-color: var(--sg-sky); background: rgba(170, 225, 250, .12); }

.token.comment, .token.prolog, .token.doctype, .token.cdata { color: var(--sg-code-dim); font-style: italic; }
.token.punctuation, .token.operator { color: rgba(220, 234, 247, .72); }
.token.keyword, .token.boolean, .token.atrule, .token.important { color: var(--sg-code-key); font-weight: 700; }
.token.string, .token.char, .token.attr-value, .token.regex { color: var(--sg-code-str); }
.token.number, .token.constant, .token.symbol { color: var(--sg-code-num); }
.token.function, .token.class-name { color: #ffffff; }
.token.property, .token.tag, .token.attr-name { color: #cfe6f7; }
.token.parameter { color: #dceaf7; }

/* URL blocks. The scheme, the slashes and the separators are scaffolding and
   stay quiet; what is coloured is what the reader has to look at — the address
   to substitute, the method being called, and the parameters. */
.token.scheme, .token.scheme-delimiter, .token.authority-delimiter,
.token.path-separator, .token.query-delimiter, .token.pair-delimiter { color: var(--sg-code-dim); }
.token.host { color: var(--sg-code-key); font-weight: 700; }
.token.path { color: #ffffff; }
.token.key { color: #cfe6f7; }
.token.value { color: var(--sg-code-str); }

.sg-wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.sg-wide { width: 100%; max-width: 1240px; margin-inline: auto; padding-inline: var(--gutter); }

.sg-mono { font-family: var(--sg-mono); }
.sg-eyebrow {
  font-size: 11.5px; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--sg-blue); margin: 0 0 .6em;
}
/* Text for a screen reader that the page does not need to show — the sighted
 * reader can watch a new window open; a screen reader user cannot. */
.sg-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--sg-navy); color: #fff; padding: 12px 18px;
  border-radius: 0 0 8px 0; font-weight: 800; border: 0;
}
.skip:focus { left: 0; }

/* --- 3. Site chrome ------------------------------------------------------ */
.site-header {
  position: sticky; top: 0; z-index: 90;
  background: rgba(255,255,255,.92); backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--sg-line);
}
.site-header__bar { height: var(--header-h); display: flex; align-items: center; gap: 10px; }
/* The bar carries brand + 7 menus + search + language. Capping it at the
   content width pushed the switcher off screen at 100 % zoom, so it runs
   wider than the rest of the page and the nav only appears when it fits. */
.site-header .sg-wide { max-width: 1600px; }
.site-header__bar > .brand { flex: none; }
.site-header__bar > nav { min-width: 0; }

.brand { display: flex; align-items: center; gap: 9px; border: 0; }
.brand:hover { border: 0; }
.brand__mark {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  background: linear-gradient(135deg, var(--sg-navy) 0%, var(--sg-midnight) 100%);
  display: grid; place-items: center; color: #fff;
}
.brand__mark svg { width: 15px; height: 15px; }
.brand__name { font-weight: 800; font-size: 16px; color: var(--sg-midnight); letter-spacing: -.02em; }
.brand__tag { display: block; font-size: 10px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--sg-muted); }
.brand + nav { margin-right: auto; }
.site-header__bar > .brand { margin-right: auto; }

.hbtn {
  appearance: none; border: 1px solid var(--sg-line); background: #fff; color: var(--sg-midnight);
  height: 36px; padding: 0 12px; border-radius: 9px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 700;
  display: inline-flex; align-items: center; gap: 7px;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.hbtn:hover { border-color: var(--sg-blue); color: var(--sg-navy); background: var(--sg-tint); }
.hbtn svg { width: 16px; height: 16px; flex: none; }
.hbtn__label { display: none; }
@media (min-width: 560px) { .hbtn__label { display: inline; } }

/* The desktop menu needs room for nine sections and the three controls beside
   them. Measured: the sections take 1,180 px and the controls 202, so below
   about 1,400 the menu runs underneath the search and language buttons rather
   than wrapping — it looks like a rendering fault and is a width problem.
   Both the rule below and the drawer's rule have to use the same number, or
   there is a band where the drawer and the menu are both visible.
   1,420 rather than 1,400: at 1,400 the last item's click target overlaps the
   search button by 8 px even though the text looks clear of it. */
.nav-desktop { display: none; }
@media (min-width: 1420px) {
  .nav-desktop { display: flex; gap: 1px; list-style: none; margin: 0 8px 0 0; padding: 0; }
  .nav-desktop > li { position: relative; margin: 0; }
  .nav-desktop__top {
    display: inline-flex; align-items: center; gap: 4px; padding: 8px 9px;
    font-size: 14px; font-weight: 700; color: var(--sg-midnight); letter-spacing: -.005em;
    border: 0; border-radius: 8px; white-space: nowrap;
  }
  .nav-desktop__top:hover, .nav-desktop li:focus-within .nav-desktop__top { background: var(--sg-tint); color: var(--sg-navy); border: 0; }
  .nav-desktop__panel {
    position: absolute; top: calc(100% + 6px); left: 0; min-width: 268px;
    background: #fff; border: 1px solid var(--sg-line); border-radius: var(--sg-r);
    box-shadow: var(--sg-shadow); padding: 8px; margin: 0; list-style: none;
    opacity: 0; visibility: hidden; transform: translateY(-4px); transition: .15s ease;
  }
  .nav-desktop li:hover > .nav-desktop__panel,
  .nav-desktop li:focus-within > .nav-desktop__panel { opacity: 1; visibility: visible; transform: none; }
  .nav-desktop__panel li { margin: 0; }
  .nav-desktop__panel a { display: block; padding: 8px 10px; border: 0; border-radius: 7px; font-size: 14.5px; color: var(--sg-midnight); }
  .nav-desktop__panel a:hover { background: var(--sg-tint); color: var(--sg-navy); }
  .menu-toggle { display: none; }
}
.caret { width: 11px; height: 11px; opacity: .55; }

.drawer {
  position: fixed; inset: var(--header-h) 0 0 auto; width: min(400px, 100%);
  background: #fff; border-left: 1px solid var(--sg-line);
  z-index: 95; overflow-y: auto; overscroll-behavior: contain;
  transform: translateX(100%); transition: transform .24s cubic-bezier(.4,0,.2,1); visibility: hidden;
}
.drawer[data-open="true"] { transform: none; visibility: visible; }
.drawer__inner { padding: 10px var(--gutter) 60px; }
.drawer__section { border-bottom: 1px solid var(--sg-line); }
.drawer__toggle {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: none; border: 0; padding: 15px 2px; cursor: pointer;
  font: inherit; font-weight: 800; font-size: 16px; color: var(--sg-midnight); text-align: left;
}
.drawer__toggle .caret { transition: transform .18s ease; }
.drawer__toggle[aria-expanded="true"] .caret { transform: rotate(180deg); }
.drawer__list { list-style: none; margin: 0; padding: 0 0 12px; }
.drawer__list li { margin: 0; }
.drawer__list a { display: block; padding: 10px 13px; border: 0; border-left: 2px solid var(--sg-line); color: var(--sg-muted); font-size: 15px; }
.drawer__list a:hover, .drawer__list a[aria-current="page"] { border-left-color: var(--sg-blue); background: var(--sg-tint); color: var(--sg-navy); }
.scrim { position: fixed; inset: 0; background: rgba(18,42,79,.45); z-index: 94; opacity: 0; visibility: hidden; transition: opacity .2s ease; }
.scrim[data-open="true"] { opacity: 1; visibility: visible; }
@media (min-width: 1420px) { .drawer, .scrim { display: none; } }

/* Search */
.search-modal { position: fixed; inset: 0; z-index: 120; display: none; padding: 8vh 16px 16px; background: rgba(18,42,79,.5); }
.search-modal[data-open="true"] { display: block; }
.search-modal__panel { max-width: 640px; margin-inline: auto; background: #fff; border-radius: var(--sg-r); box-shadow: 0 24px 60px rgba(18,42,79,.3); overflow: hidden; }
.search-modal__field { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--sg-line); }
.search-modal__field svg { width: 18px; height: 18px; color: var(--sg-blue); flex: none; }
.search-modal__input { flex: 1; border: 0; outline: 0; font: inherit; font-size: 17px; color: var(--sg-midnight); background: none; }
.search-modal__input::placeholder { color: var(--sg-muted); }
.search-modal__esc { font-family: var(--sg-mono); font-size: 11px; color: var(--sg-muted); border: 1px solid var(--sg-line); border-radius: 5px; padding: 3px 6px; }
.search-results { list-style: none; margin: 0; padding: 6px; max-height: min(58vh, 440px); overflow-y: auto; }
.search-results li { margin: 0; }
.search-results a { display: block; padding: 11px 12px; border: 0; border-radius: 9px; }
.search-results a:hover, .search-results a:focus-visible { background: var(--sg-tint); }
.search-results__meta { display: block; font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--sg-blue); }
.search-results__title { display: block; font-weight: 800; color: var(--sg-midnight); }
.search-results__desc { display: block; font-size: 14px; color: var(--sg-muted); }
.search-empty { padding: 20px 16px; color: var(--sg-muted); font-size: 15px; }

/* Language switcher */
.lang { position: relative; }
.lang__menu {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 190px;
  background: #fff; border: 1px solid var(--sg-line); border-radius: var(--sg-r);
  box-shadow: var(--sg-shadow); padding: 6px; margin: 0; list-style: none; z-index: 100;
}
.lang__menu[hidden] { display: none; }
.lang__menu li { margin: 0; }
.lang__opt {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 10px; border: 0; background: none; border-radius: 7px;
  font: inherit; font-size: 15px; color: var(--sg-midnight); text-align: left; cursor: pointer;
}
.lang__opt:hover { background: var(--sg-tint); color: var(--sg-navy); }
.lang__opt[aria-current="true"] { background: var(--sg-tint); color: var(--sg-navy); font-weight: 800; }
.lang__opt[aria-disabled="true"] { color: var(--sg-muted); cursor: default; }
.lang__opt[aria-disabled="true"]:hover { background: none; }
.lang__soon { font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--sg-muted); }

/* Menu entries for guides that have not been migrated yet. Same treatment as an
   untranslated language: listed, so the reader can see it is coming, but not a
   link, because there is nothing to link to. */
.nav-soon {
  display: flex; align-items: baseline; gap: 8px; cursor: default;
  color: var(--sg-muted); opacity: .75;
}
.nav-soon__tag { font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
.nav-desktop__panel .nav-soon { padding: 8px 10px; font-size: 14.5px; }
.drawer__list .nav-soon { padding: 10px 13px; border-left: 2px solid var(--sg-line); font-size: 15px; }

/* --- 4. Guide hero -------------------------------------------------------
   Full-bleed navy band, with the content shell pulled up so the first card
   starts inside the blue — the IHC calculator's proportions.
   ------------------------------------------------------------------------ */
.sg-band {
  background: linear-gradient(135deg, var(--sg-navy) 0%, var(--sg-midnight) 100%);
  color: #fff;
  padding: 30px 0 104px;
}
@media (max-width: 700px) { .sg-band { padding: 24px 0 92px; } }

.sg-hero { color: #fff; }
.sg-hero h1 { color: #fff; margin: 0 0 10px; max-width: 22ch; }
.sg-hero .sg-eyebrow { color: var(--sg-sky); }

/* The shell: light field that carries the white cards, overlapping the band */
.sg-shell {
  max-width: var(--wrap);
  margin: -78px auto 0;
  padding: 20px 20px 34px;
  background: var(--sg-shell);
  border-radius: 18px;
  position: relative;
  z-index: 1;
}
@media (max-width: 700px) {
  .sg-shell { margin-top: -70px; padding: 14px 14px 26px; border-radius: 14px; }
}

.sg-sub { font-size: 16px; color: var(--sg-sky); margin: 0 0 14px; max-width: 60ch; }
.sg-updated { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: rgba(255,255,255,.55); margin: 0; }

/* --- 5. Cards ------------------------------------------------------------ */
.sg-card {
  background: var(--sg-paper); border: 1px solid var(--sg-line);
  border-radius: var(--sg-r); box-shadow: var(--sg-shadow);
  padding: 24px 26px; margin: 0 0 16px;
}
@media (max-width: 600px) { .sg-card { padding: 20px; } }
.sg-card > h2:first-child, .sg-card > h3:first-child { margin-top: 0; }
.sg-card h2 { position: relative; padding-bottom: 10px; margin-bottom: 14px; }
.sg-card h2::after { content: ""; position: absolute; left: 0; bottom: 0; width: 42px; height: 3px; border-radius: 2px; background: var(--sg-sky); }
.sg-lead { font-size: 17px; color: var(--sg-muted); }

/* Safety notice */
.sg-safety {
  background: var(--sg-amber-bg); border: 1px solid var(--sg-amber-line);
  border-left: 4px solid #e0a63c; border-radius: var(--sg-r);
  padding: 20px 24px; margin: 0 0 16px;
}
.sg-safety h2, .sg-safety h3 { color: var(--sg-amber); margin-top: 0; font-size: 17px; }
/* An h3 in a safety block is a subsection of the notice, not a second notice.
   Sharing the h2's 17px and weight made the two read as siblings — the amber
   is what marks them both as part of the block, so size is the only thing
   left to carry the hierarchy. One block on the site has an h3 today, on
   garage-door-control. */
.sg-safety h3 { font-size: 15px; margin-top: 1.1em; }
.sg-safety h2::after { display: none; }
.sg-safety p, .sg-safety li { color: #6b5316; }

/* Before-you-start caveat — deliberately NOT a safety notice.
 *
 * The amber card above means mains voltage and the possibility of injury.
 * This one means "this will surprise you": a script that uses most of the
 * device's memory, a preview API, a limit that costs an afternoon. They must
 * not look alike. A reader who learns that amber sometimes means "uses a lot
 * of RAM" starts skimming amber, and then it means nothing on the ten pages
 * where it means the other thing.
 *
 * So this shares neither colour nor shape with .sg-safety: a cool ground
 * instead of amber, and a rule across the top instead of a bar down the left.
 * Different at a glance, before any of the words are read. */
.sg-caveat {
  background: var(--sg-shell); border: 1px solid var(--sg-line);
  border-top: 3px solid var(--sg-blue); border-radius: var(--sg-r);
  padding: 20px 24px; margin: 0 0 16px;
}
.sg-caveat h2, .sg-caveat h3 { color: var(--sg-midnight); margin-top: 0; font-size: 17px; }
.sg-caveat h2::after { display: none; }
.sg-caveat p, .sg-caveat li { color: var(--sg-muted); }

/* Note / tip callouts inside cards */
.sg-note {
  background: var(--sg-tint); border: 1px solid var(--sg-line);
  border-left: 3px solid var(--sg-blue); border-radius: var(--sg-r-sm);
  padding: 14px 16px; margin: 16px 0;
}
.sg-note h4 { margin: 0 0 .4em; color: var(--sg-navy); }
.sg-note--warning { background: var(--sg-amber-bg); border-color: var(--sg-amber-line); border-left-color: #e0a63c; }
.sg-note--warning h4 { color: var(--sg-amber); }
.sg-note--tip { background: #ecfaf1; border-color: #b9e6cd; border-left-color: #37a06a; }
.sg-note--tip h4 { color: #14532d; }
.sg-note p:last-child { margin-bottom: 0; }

/* --- 6. Steps ------------------------------------------------------------ */
.sg-steps { margin: 0; }
.sg-step {
  background: var(--sg-paper); border: 1px solid var(--sg-line);
  border-radius: var(--sg-r); box-shadow: var(--sg-shadow);
  margin: 0 0 16px; overflow: hidden;
}
.sg-step__head { display: flex; gap: 15px; align-items: flex-start; padding: 20px 24px 0; }
.sg-step__num {
  flex: none; width: 44px; height: 44px; border-radius: 12px;
  background: var(--sg-navy); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.sg-step__kicker { display: block; margin-bottom: 4px; font-size: 11.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--sg-blue); }
.sg-step__head h3 { margin: 0; font-size: 20px; }
.sg-step__body { padding: 14px 24px 22px 83px; }
.sg-step__body > h4:first-child { margin-top: 0; }
.sg-step__body h4 { font-size: 15.5px; margin: 1.2em 0 .4em; }
@media (max-width: 600px) {
  .sg-step__head { padding: 18px 18px 0; gap: 12px; }
  .sg-step__num { width: 38px; height: 38px; font-size: 17px; }
  .sg-step__body { padding: 12px 18px 20px; }
}

/* Terminals */
.sg-terminals { display: grid; grid-template-columns: 56px 1fr; gap: 6px 14px; margin: 0 0 14px; font-size: 15px; }
.sg-terminals dt {
  font-family: var(--sg-mono); font-weight: 800; color: var(--sg-navy);
  background: var(--sg-tint); border: 1px solid var(--sg-line);
  border-radius: 5px; padding: 2px 6px; text-align: center; align-self: start;
}
.sg-terminals dd { margin: 0; align-self: center; }

/* --- 7. Figures — small on the page, enlarge on click -------------------- */
.sg-figure { margin: 16px 0 4px; text-align: center; }
.sg-zoom { position: relative; display: inline-block; max-width: 100%; }
.sg-zoom::after {
  content: ""; position: absolute; right: 10px; bottom: 10px; width: 28px; height: 28px;
  border-radius: 8px; background: rgba(18,42,79,.82) center/15px 15px no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6M11 8v6M8 11h6'/%3E%3C/svg%3E");
  pointer-events: none; transition: transform .15s ease;
}
.sg-zoom:hover::after { transform: scale(1.08); }
.sg-figure img {
  max-width: 100%; height: auto; display: block; margin: 0 auto;
  border: 1px solid var(--sg-line); border-radius: 12px; background: #fff;
  cursor: zoom-in; transition: opacity .15s ease;
}
.sg-figure img:hover { opacity: .93; }
/* min() and not a bare px value, because these override the base rule above
   rather than adding to it. `max-width: 430px` is a fixed width once the
   container is narrower than 430: the image stops shrinking, runs past the
   card, and is clipped. Measured at a 412 px viewport the content box inside
   a step is 346 px and inside a card 342 px, so a diagram figure overflowed
   by 84–88 px on every phone. min() keeps the cap on a wide screen and hands
   the base rule back on a narrow one. */
.sg-figure--diagram img { max-width: min(430px, 100%); }
.sg-figure--phone img { max-width: min(230px, 100%); }
/* --wide is the only modifier that does not shrink. It is for a screenshot
   whose subject is the width — a full window, an overview at 2.6:1 — where a
   430 px cap would make the thing being pointed at unreadable. It takes the
   content column and no more. Stated rather than left to the base rule above,
   because a size class that works by not existing is one nobody can find. */
.sg-figure--wide img { max-width: 100%; }
.sg-figure figcaption { font-size: 13.5px; color: var(--sg-muted); margin-top: 9px; }

/* Lightbox */
.sg-lightbox {
  position: fixed !important; inset: 0; z-index: 9999;
  background: rgba(9,22,40,.92); display: none;
  align-items: center; justify-content: center; padding: 24px;
  cursor: zoom-out;
}
.sg-lightbox.is-open { display: flex; }
.sg-lightbox img { max-width: 96vw; max-height: 90vh; border-radius: 10px; background: #fff; }
.sg-lightbox__close {
  position: absolute; top: 18px; right: 20px; width: 40px; height: 40px;
  border-radius: 50%; border: 1px solid rgba(255,255,255,.3); background: rgba(255,255,255,.1);
  color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 20px;
}

/* --- 8. Tables ----------------------------------------------------------- */
/* The overflow-x is the whole point of this class and it was missing. The name
   promised scrolling and the declaration did not exist, so a table wider than
   the card simply grew out of it: clipped at the card edge by
   .sg-step { overflow: hidden } inside a step, and painted past the card and
   then hidden by html, body { overflow-x: hidden } inside a plain card. Either
   way no scrollbar ever appeared to give it away. Measured at 320 px, the
   worst was 483 px of table in a 250 px content box. Same class of fault as
   finding 116: a rule that reads correctly and does nothing.
   `table { width: 100% }` below is a minimum, not a maximum — content that
   cannot fit makes the table wider regardless. */
.sg-table-scroll { margin: 16px 0; overflow-x: auto; }

/* A scroll shadow, so a table that can be moved does not read as one that was
   cut off. Needed because on iOS the scrollbar is invisible until you scroll,
   which leaves no hint at all that there is more to the right.

   Four background layers and no JavaScript. Earlier layers paint on top, so
   the order is: left cover, right cover, left shadow, right shadow.

   The covers are `local` — they scroll with the content. The shadows are
   `scroll` — they stay pinned to the box. That difference is the whole trick:

   - At rest the left cover sits exactly over the left shadow and hides it.
     Scroll right and the cover travels away with the content, revealing the
     shadow: there is now something to the left.
   - The right cover is positioned at the end of the content, so at rest it is
     off to the right and the right shadow shows. Scroll fully right and the
     cover arrives and hides it: there is nothing more that way.

   A table that fits never scrolls, so neither cover ever leaves its shadow and
   no shadow is ever seen. That is the correct result rather than a missing
   one — a permanent shadow on a table that fits would be a bug.

   Colours from the palette: --sg-paper for the covers, because the card is
   white, and --sg-line for the shadows. Black would read as a bruise on a pale
   blue page. The transparent stops are written as rgba of those same two
   values, because `transparent` computes to rgba(0,0,0,0) and Safari
   interpolates towards black through the gradient. */
.sg-table-scroll {
  background:
    linear-gradient(to right, var(--sg-paper) 30%, rgba(255,255,255,0)) left center,
    linear-gradient(to left,  var(--sg-paper) 30%, rgba(255,255,255,0)) right center,
    linear-gradient(to right, var(--sg-line), rgba(219,230,239,0)) left center,
    linear-gradient(to left,  var(--sg-line), rgba(219,230,239,0)) right center;
  background-repeat: no-repeat;
  background-size: 36px 100%, 36px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* Focusable, so the box can be reached and scrolled with the arrow keys. The
   ring is the site's own; without it a keyboard user lands somewhere invisible. */
.sg-table-scroll:focus-visible { outline: 2px solid var(--sg-blue); outline-offset: 2px; border-radius: 4px; }
table { width: 100%; border-collapse: collapse; font-size: 15px; }
thead th {
  text-align: left; background: var(--sg-tint); color: var(--sg-navy);
  padding: 10px 12px; font-size: 11.5px; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; border-bottom: 1px solid var(--sg-line);
}
tbody td { padding: 10px 12px; border-bottom: 1px solid var(--sg-line); vertical-align: top; }
/* UNUSED. Nothing on the site carries .table-stack and no cell carries a
   data-label, so none of the five rules below has ever applied — verified in
   the built HTML, not assumed. It is kept because it is the better answer than
   horizontal scrolling: it turns each row into a card with its field names
   visible, which is what a table on a phone should be.
   To take it into use, two things are needed together: the class on each
   <table>, and data-label="<column heading>" on every <td>, since the td::before
   rule reads that attribute for the label. Doing that by hand across 28 tables
   is the reason it was never finished; a markdown-it rule that adds both from
   the table's own <thead> would do it in one place. Until then the tables
   scroll. */
@media (max-width: 700px) {
  .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .table-stack tbody tr { display: block; border: 1px solid var(--sg-line); border-radius: var(--sg-r-sm); margin-bottom: 12px; overflow: hidden; }
  .table-stack tbody td { display: flex; gap: 12px; justify-content: space-between; padding: 9px 12px; }
  .table-stack tbody td::before { content: attr(data-label); flex: none; max-width: 46%; font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--sg-muted); }
  .table-stack tbody td:first-child { background: var(--sg-tint); font-weight: 800; }
}

/* --- 9. Video, related, pager ------------------------------------------- */
/* Click-to-load facade. Nothing is requested from YouTube until the reader
   presses play, so the page stays free of third-party requests on load. */
.sg-video { margin: 4px 0 0; }
.sg-video__play {
  position: relative; display: block; width: 100%; padding: 0; border: 0; cursor: pointer;
  background: var(--sg-midnight); border-radius: var(--sg-r-sm); overflow: hidden; line-height: 0;
}
.sg-video__play img { width: 100%; height: auto; display: block; opacity: .85; transition: opacity .2s ease, transform .5s ease; }
.sg-video__play:hover img { opacity: 1; transform: scale(1.02); }
.sg-video__btn {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 68px; height: 48px; border-radius: 12px; background: rgba(18,42,79,.86);
  border: 1px solid rgba(255,255,255,.28); transition: background .2s ease;
}
.sg-video__btn::after {
  content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-40%, -50%);
  border-style: solid; border-width: 9px 0 9px 15px; border-color: transparent transparent transparent #fff;
}
.sg-video__play:hover .sg-video__btn { background: var(--sg-navy); }
.sg-video iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: var(--sg-r-sm); display: block; }
.sg-video__note { font-size: 12.5px; color: var(--sg-muted); margin: 7px 0 0; }
.sg-video__watch { white-space: nowrap; }
/* Credit and the language note survive playback; the "press play" line does not,
   since by then the reader has. */
.sg-video__credit { font-size: 12.5px; color: var(--sg-muted); margin: 5px 0 0; }
.sg-video__lang {
  font-size: 13px; color: var(--sg-midnight); margin: 8px 0 0;
  border-left: 3px solid var(--sg-line); padding: 2px 0 2px 11px;
}
.sg-video.is-loaded .sg-video__note { display: none; }

.sg-related__grid { display: grid; gap: 12px; grid-template-columns: 1fr; margin-top: 4px; }
@media (min-width: 620px) { .sg-related__grid { grid-template-columns: 1fr 1fr; } }
.sg-related__grid a {
  display: block; padding: 15px 17px; border: 1px solid var(--sg-line);
  border-radius: var(--sg-r-sm); background: var(--sg-paper);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.sg-related__grid a:hover { border-color: var(--sg-blue); box-shadow: var(--sg-shadow); transform: translateY(-2px); }
.sg-related__grid strong { display: block; color: var(--sg-navy); margin-bottom: 3px; }
.sg-related__grid span { font-size: 14px; color: var(--sg-muted); }

/* A guide the section front knows about but that has not been migrated yet.
   Same box, dashed and not clickable, so the gap is visible rather than a
   link that 404s. */
.sg-related__soon {
  padding: 15px 17px; border: 1px dashed var(--sg-line);
  border-radius: var(--sg-r-sm); background: transparent;
}
.sg-related__soon strong { display: block; color: var(--sg-muted); margin-bottom: 3px; }
.sg-related__soon span { font-size: 14px; color: var(--sg-muted); font-style: italic; }

/* A link to a tool. A related card is a quiet white box that promises more
   reading; this promises something that does work for you, so it reads as a
   control rather than a card: tinted, with an accent bar down the left edge
   and the action stated first. The reader can tell the two apart before
   clicking, which is the whole point of it having its own style. */
.sg-tool {
  display: block; position: relative; margin: 18px 0;
  padding: 16px 18px 16px 22px; border: 1px solid var(--sg-line);
  border-left: 4px solid var(--sg-blue);
  border-radius: var(--sg-r-sm); background: var(--sg-tint);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.sg-tool:hover { border-color: var(--sg-blue); border-left-color: var(--sg-navy); box-shadow: var(--sg-shadow); transform: translateY(-2px); }
.sg-tool__eyebrow {
  display: block; font-size: 11px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--sg-blue-600); margin-bottom: 4px;
}
.sg-tool__title { display: block; font-size: 17px; color: var(--sg-navy); }
/* The arrow is decorative and sits after the title, so a screen reader reads
   the eyebrow, the name and the note — not a stray character. */
.sg-tool__title::after { content: " \2192"; color: var(--sg-blue); }
.sg-tool__note { display: block; font-size: 14px; color: var(--sg-muted); margin-top: 3px; }
.sg-tool__host { display: block; font-size: 12px; color: var(--sg-muted); margin-top: 7px; }

.sg-pager { display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; margin: 22px 0 40px; }
.sg-pager a { font-size: 14px; font-weight: 800; border: 0; }

/* Breadcrumbs */
.crumbs { padding: 14px 0 0; font-size: 13px; color: rgba(255,255,255,.6); }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; }
.crumbs li { margin: 0; }
.crumbs li + li::before { content: "\002F"; margin-right: 6px; color: rgba(255,255,255,.35); }
.crumbs a { color: rgba(255,255,255,.72); border: 0; }
.crumbs a:hover { color: #fff; }

/* --- 10. Footer ---------------------------------------------------------- */
.site-footer { background: #fff; border-top: 1px solid var(--sg-line); padding: 44px 0 24px; font-size: 15px; color: var(--sg-muted); margin-top: 40px; }
.site-footer h4 { color: var(--sg-midnight); font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase; margin-bottom: 14px; }
.site-footer a { color: var(--sg-muted); border: 0; }
.site-footer a:hover { color: var(--sg-navy); text-decoration: underline; }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: 8px; }
.footer-grid { display: grid; gap: 30px; grid-template-columns: 1fr; }
@media (min-width: 760px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .footer-grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }
.footer-note { margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--sg-line); font-size: 13px; display: flex; flex-wrap: wrap; gap: 8px 20px; justify-content: space-between; }
.disclaimer { background: var(--sg-shell); border: 1px solid var(--sg-line); border-radius: var(--sg-r-sm); padding: 14px 16px; font-size: 14px; margin-top: 16px; }

/* --- 11. Safety net ------------------------------------------------------ */
/* Kept from the sticky-TOC era. No longer load-bearing, but it still stops
   theme wrappers from clipping the lightbox. */
html, body { overflow-x: hidden; }
.sg-page, .sg-page * { overflow: visible; }

/* --- 12. Print ----------------------------------------------------------- */
@page { margin: 16mm 14mm; }

@media print {
  .site-header, .drawer, .scrim, .search-modal, .site-footer, .sg-pager, .crumbs, .sg-lightbox, .skip { display: none !important; }

  /* Both, not just body. `html` carries --sg-page, and the print block used to
     reset only `body` — so wherever the content stopped short of the paper the
     html background showed through as a pale blue block, most visibly as a
     third of a page at the end of a document. Backgrounds print only when the
     reader ticks the box, which is why it took until somebody did. */
  html, body { background: #fff; }
  body { font-size: 11pt; color: #111; }
  .sg-band { background: none !important; padding: 0 0 12px; border-bottom: 2px solid #000; }
  .sg-shell { margin: 0; padding: 0; background: none; }

  /* The hero prints white-on-white without these three lines, and did for
     every page on the site until somebody printed one.

     The band's navy gradient is dropped above, correctly — but `.sg-hero h1`
     sets `color: #fff` at a specificity the old print block never matched. It
     restyled the same selector for box-shadow and border and left the colour
     alone, so the h1 came out white on white: an empty bordered rectangle
     where the title should be. The eyebrow and lead did the same in
     --sg-sky, which is legible on navy and not on paper. */
  .sg-hero, .sg-hero h1 { color: #111; }
  .sg-hero .sg-sub { color: #333; }
  .sg-hero .sg-eyebrow, .sg-updated { color: #555; }

  /* A border belongs round a card, not round a heading. The old rule put one
     round the h1, the lead and the eyebrow as well, which is where the thin
     empty frame on the printed page came from. */
  .sg-card, .sg-step { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; }

  /* The safety block and the callouts hold together too — they were the two
     boxes the rule above forgot, and they are the two where a split costs most.

     A safety notice carries four things: that the work is on mains voltage,
     that it needs a qualified electrician, isolate-lock-verify, and the
     national rules. Half of that at the foot of a page is worse than none,
     because the reader has seen a safety notice and believes he has read it.
     A warning whose heading ends one page and whose text begins the next is
     not read as a warning at all.

     Latent rather than active when this was written: every safety block on the
     site sits high on page one, so none of them splits on A4 today. It is one
     longer guide away from mattering, and the same rule covers the callouts,
     which sit anywhere. */
  .sg-safety, .sg-caveat, .sg-note { break-inside: avoid; }
  .sg-hero h1, .sg-hero .sg-sub, .sg-hero .sg-eyebrow { box-shadow: none; border: 0; }

  .sg-figure { break-inside: avoid; break-after: avoid; }
  h1, h2, h3, h4 { break-after: avoid; break-inside: avoid; }
  .sg-figure img { cursor: default; }
  a { color: #000; border-bottom: 0; }
  .sg-video { display: none; }
}
