/* Site theme: Nocturne retuned to a navy palette. Structure and layout follow
   the old Gatsby Cara site, but the hues do not: its warm orange accent and
   multicoloured shapes tinted the whole page, so everything here stays in one
   cool family. Two colour modes, dark first.
   This is the ONE place the tokens are set; no page defines its own block. */

:root {
  /* Shape palette. Cool only: the warm icon colours the old site used are
     what put an orange cast over everything. Variation here is temperature
     and depth, not hue. */
  --ic-mist: #cbd9ea;
  --ic-ice: #a8cdf2;
  --ic-steel: #7fb2e5;
  --ic-azure: #4a90d9;
  --ic-sapphire: #2b6cb0;
  --ic-slate: #7086a4;
  --ic-deep: #1e3a5f;

  --shell-max: 1280px;
  --radius-md: 10px; --radius-lg: 16px;

  /* Section gradients, all in the navy family. Cara's structure, restrained
     palette: they differ by depth and temperature rather than by hue. */
  --grad-1: linear-gradient(to right, #16233c 0%, #2b6cb0 100%);
  --grad-2: linear-gradient(to right, #1a365d 0%, #4a90d9 100%);
  --grad-3: linear-gradient(to right, #17303f 0%, #3f7fa8 100%);
  --grad-4: linear-gradient(to right, #23304f 0%, #7fb2e5 100%);
}

/* ---------- dark, the default, as the old site shipped ---------- */

:root, :root[data-theme="dark"] {
  --color-bg: #0f1626;
  --color-surface: #162033;
  --color-surface-2: #1d2941;
  --color-text: #dde5f2;
  --color-heading: #ffffff;
  --color-accent: #7fb2e5;
  --color-accent-strong: #a8cdf2;
  --color-divider: #253349;

  /* 100 is the most contrast against the ground, 900 the least. */
  --color-neutral-100: #f4f7fc; --color-neutral-200: #e4ebf6; --color-neutral-300: #ccd8ea;
  --color-neutral-400: #aabbd4; --color-neutral-500: #8b9dba; --color-neutral-600: #66789a;
  --color-neutral-700: #43587a; --color-neutral-800: #253349; --color-neutral-900: #162033;

  --shape-ink: #cbd9ea;
  --shadow-sm: 0 0 0 1px rgba(221, 229, 242, 0.10);
  --shadow-md: 0 0 0 1px rgba(221, 229, 242, 0.10), 0 8px 24px rgba(0, 0, 0, 0.50);
  --shadow-lg: 0 0 0 1px rgba(221, 229, 242, 0.13), 0 18px 48px rgba(0, 0, 0, 0.62);
  --grad-strength: 1;
  --wash-strength: 0.85;

  /* Flavour bars, dim to bright. Screen only; the print cards carry their
     own ink. Referenced as var(--bar-N) from inline styles, so they follow
     the colour mode without app.js having to re-render. */
  --bar-0: #253349; --bar-1: #2b4a72; --bar-2: #35618f;
  --bar-3: #4a90d9; --bar-4: #7fb2e5; --bar-5: #a8cdf2;
  --pbar-0: #2b4a72; --pbar-1: #35618f; --pbar-2: #3f7cba;
  --pbar-3: #4a90d9; --pbar-4: #7fb2e5; --pbar-5: #bcdcf7;
}

/* ---------- light ---------- */

:root[data-theme="light"] {
  --color-bg: #f6f8fc;
  --color-surface: #ffffff;
  --color-surface-2: #eaf0f8;
  --color-text: #1f2a3d;
  --color-heading: #0b1220;
  --color-accent: #2b5f9e;
  --color-accent-strong: #1e4676;
  --color-divider: #dae3ef;

  /* The ramp flips so every role keeps its meaning: 100 still means the most
     contrast against the ground, 900 still means a barely-there surface. */
  --color-neutral-100: #0b1220; --color-neutral-200: #1f2a3d; --color-neutral-300: #3a4a63;
  --color-neutral-400: #5a6d8a; --color-neutral-500: #6b7e9b; --color-neutral-600: #93a5bf;
  --color-neutral-700: #c2cfe0; --color-neutral-800: #dae3ef; --color-neutral-900: #eaf0f8;

  --shape-ink: #3a4a63;
  --shadow-sm: 0 1px 2px rgba(15, 22, 38, 0.08), 0 0 0 1px rgba(15, 22, 38, 0.06);
  --shadow-md: 0 2px 6px rgba(15, 22, 38, 0.10), 0 1px 2px rgba(15, 22, 38, 0.06);
  --shadow-lg: 0 10px 30px rgba(15, 22, 38, 0.14), 0 2px 6px rgba(15, 22, 38, 0.08);
  --grad-strength: 0.7;
  --wash-strength: 0.45;

  --bar-0: #eaf0f8; --bar-1: #bcdcf7; --bar-2: #7fb2e5;
  --bar-3: #4a90d9; --bar-4: #2b6cb0; --bar-5: #1a365d;
  --pbar-0: #7fb2e5; --pbar-1: #4a90d9; --pbar-2: #2b6cb0;
  --pbar-3: #24568c; --pbar-4: #1a365d; --pbar-5: #12253f;
}

/* First visit with no stored choice follows the operating system. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --color-bg: #f6f8fc;
    --color-surface: #ffffff;
    --color-surface-2: #eaf0f8;
    --color-text: #1f2a3d;
    --color-heading: #0b1220;
    --color-accent: #2b5f9e;
    --color-accent-strong: #1e4676;
    --color-divider: #dae3ef;

    --color-neutral-100: #0b1220; --color-neutral-200: #1f2a3d; --color-neutral-300: #3a4a63;
    --color-neutral-400: #5a6d8a; --color-neutral-500: #6b7e9b; --color-neutral-600: #93a5bf;
    --color-neutral-700: #c2cfe0; --color-neutral-800: #dae3ef; --color-neutral-900: #eaf0f8;

    --shape-ink: #3a4a63;
    --shadow-sm: 0 1px 2px rgba(15, 22, 38, 0.08), 0 0 0 1px rgba(15, 22, 38, 0.06);
    --shadow-md: 0 2px 6px rgba(15, 22, 38, 0.10), 0 1px 2px rgba(15, 22, 38, 0.06);
    --shadow-lg: 0 10px 30px rgba(15, 22, 38, 0.14), 0 2px 6px rgba(15, 22, 38, 0.08);
    --grad-strength: 0.7;
    --wash-strength: 0.45;

    --bar-0: #eaf0f8; --bar-1: #bcdcf7; --bar-2: #7fb2e5;
    --bar-3: #4a90d9; --bar-4: #2b6cb0; --bar-5: #1a365d;
    --pbar-0: #7fb2e5; --pbar-1: #4a90d9; --pbar-2: #2b6cb0;
    --pbar-3: #24568c; --pbar-4: #1a365d; --pbar-5: #12253f;
  }
}

html { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
@media (prefers-color-scheme: light) { :root:not([data-theme]) { color-scheme: light; } }

body { margin: 0; background: var(--color-bg); color: var(--color-text); font-family: var(--font-body);
       -webkit-font-smoothing: antialiased; }
h1, h2, h3, h4 { color: var(--color-heading); font-weight: 500; }
a { color: var(--color-accent); }
a:hover { color: var(--color-accent-strong); }

/* Scroll chrome follows the mode. */
html { scrollbar-width: thin; scrollbar-color: var(--color-neutral-700) var(--color-bg); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--color-bg); }
::-webkit-scrollbar-thumb { background: var(--color-neutral-800); border-radius: 999px;
  border: 2px solid var(--color-bg); background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--color-neutral-700); background-clip: padding-box; }

/* ---------- shared nav ---------- */

.shell { max-width: var(--shell-max); margin: 0 auto; padding: 0 28px; }
.topnav { position: sticky; top: 0; z-index: 40; backdrop-filter: blur(10px);
          background: color-mix(in srgb, var(--color-bg) 82%, transparent);
          border-bottom: 1px solid var(--color-divider); }
.topnav .shell { display: flex; align-items: center; gap: 22px; height: 58px; }
.navbrand { display: inline-flex; align-items: center; gap: 9px; margin-right: auto;
            font-family: var(--font-heading); font-weight: 500; font-size: 15px; letter-spacing: 0.18em;
            text-transform: uppercase; color: var(--color-heading); text-decoration: none; }
.navbrand:hover { color: var(--color-accent); }
.navmark { height: 15px; width: auto; flex: none; }
/* The mark is black line art on transparent, so it inverts for the dark ground. */
:root:not([data-theme="light"]) .navmark { filter: invert(1); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .navmark { filter: none; } }
:root[data-theme="dark"] .navmark { filter: invert(1); }
.navlink { font-size: 13.5px; letter-spacing: 0.04em; color: var(--color-neutral-500); text-decoration: none; }
.navlink:hover { color: var(--color-text); }
.navlink[aria-current="page"] { color: var(--color-accent); }

/* ---------- colour mode toggle ---------- */

.modetoggle { flex: none; width: 34px; height: 34px; display: inline-flex; align-items: center;
              justify-content: center; padding: 0; cursor: pointer; border-radius: 999px;
              background: transparent; border: 1px solid var(--color-divider);
              color: var(--color-neutral-500); font-size: 15px; line-height: 1;
              transition: color .15s ease, border-color .15s ease, background .15s ease; }
.modetoggle:hover { color: var(--color-accent); border-color: var(--color-accent);
                    background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.modetoggle:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.modetoggle .i-sun { display: none; }
.modetoggle .i-moon { display: block; }
:root[data-theme="light"] .modetoggle .i-sun { display: block; }
:root[data-theme="light"] .modetoggle .i-moon { display: none; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .modetoggle .i-sun { display: block; }
  :root:not([data-theme]) .modetoggle .i-moon { display: none; }
}

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

.sitefoot { border-top: 1px solid var(--color-divider); margin-top: 72px; }
.sitefoot .shell { display: flex; flex-wrap: wrap; gap: 16px; align-items: center;
                   padding-top: 26px; padding-bottom: 34px; font-size: 12.5px; color: var(--color-neutral-500); }
.sitefoot a { color: var(--color-neutral-400); text-decoration: none; }
.sitefoot a:hover { color: var(--color-accent); }

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

.prose { font-size: 15.5px; line-height: 1.75; color: var(--color-neutral-300); }
.prose > :first-child { margin-top: 0; }
.prose p { margin: 0 0 18px; text-wrap: pretty; }
.prose h2 { font-size: 22px; margin: 38px 0 12px; }
.prose h3 { font-size: 17px; margin: 28px 0 10px; }
.prose ul, .prose ol { margin: 0 0 18px; padding-left: 22px; }
.prose li { margin-bottom: 7px; }
.prose blockquote { margin: 22px 0; padding: 2px 0 2px 18px; border-left: 2px solid var(--color-accent);
                    color: var(--color-neutral-400); }
.prose code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em;
              padding: 2px 5px; border-radius: 4px; background: var(--color-neutral-900); }
.prose pre { overflow-x: auto; padding: 16px 18px; border-radius: var(--radius-md);
             background: var(--color-neutral-900); border: 1px solid var(--color-divider); }
.prose pre code { padding: 0; background: none; }
.prose img { max-width: 100%; border-radius: var(--radius-md); }
.prose hr { border: 0; height: 1px; margin: 32px 0;
            background: linear-gradient(to right, transparent, var(--color-divider) 24px,
                        var(--color-divider) calc(100% - 24px), transparent); }

.rule, .softrule { border: 0; height: 1px;
  background: linear-gradient(to right, transparent, var(--color-divider) 24px,
              var(--color-divider) calc(100% - 24px), transparent); }

.kicker { font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-accent); }

/* ---------- small screens ---------- */

@media (max-width: 560px) {
  .shell { padding: 0 18px; }
  .topnav .shell { gap: 13px; height: 54px; }
  .navbrand { font-size: 13px; letter-spacing: 0.12em; }
  .navmark { height: 13px; }
  .navlink { font-size: 12.5px; }
  .modetoggle { width: 30px; height: 30px; font-size: 14px; }
}
@media (max-width: 380px) {
  .shell { padding: 0 14px; }
  .topnav .shell { gap: 10px; }
  .navbrand { font-size: 11.5px; letter-spacing: 0.06em; }
  .navbrand span { display: none; }
  .navmark { height: 15px; }
  .navlink { font-size: 11.5px; }
}

@media print {
  .topnav, .sitefoot { display: none !important; }
  body { background: #fff !important; color: #000 !important; }
}

/* Tables in prose. They scroll inside their own box rather than widening
   the page, which matters for the wide cheat-sheet table in the iptables post. */
.prose .tablewrap, .prose table { display: block; max-width: 100%; overflow-x: auto; }
.prose table { border-collapse: collapse; font-size: 13.5px; margin: 0 0 20px;
               white-space: nowrap; }
.prose th, .prose td { padding: 8px 14px; text-align: left; vertical-align: top;
                       border-bottom: 1px solid var(--color-divider); }
.prose th { font-weight: 500; color: var(--color-heading); font-size: 11px;
            letter-spacing: 0.1em; text-transform: uppercase; }
.prose td { color: var(--color-neutral-300); }
.prose tbody tr:last-child td { border-bottom: 0; }
