@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:wght@400;500;600;700&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');

* { box-sizing: border-box; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.grain {
  position: fixed; inset: 0; pointer-events: none; z-index: 500;
  opacity: 0.035; mix-blend-mode: overlay;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .grain { opacity: 0.06; mix-blend-mode: soft-light; }
}
:root[data-theme="dark"] .grain { opacity: 0.06; mix-blend-mode: soft-light; }

h1, h2, h3 {
  font-family: 'IBM Plex Serif', Georgia, serif;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
  color: var(--text);
}

/* BlackTor cube mark used inline: a larger one as emphasis beside a major section heading
   (.h2-icon), a smaller one as a bullet-style marker before each item in a repeating list of
   cards (.bullet-icon) -- routines, formulas, tips, full notes. Colour is set on the icon
   itself per page (see cube_icon_svg); only the outline stroke inherits from --text-muted here,
   so it reads as a light stroke in dark mode and a darker one in light mode automatically. */
.h2-icon, .bullet-icon {
  color: var(--text-muted);
  flex: none;
}
.h2-icon {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  vertical-align: -0.1em;
  margin-right: 0.32em;
}
.bullet-icon {
  display: inline-block;
  width: 0.72em;
  height: 0.72em;
  vertical-align: -0.06em;
  margin-right: 0.34em;
}

.eyebrow {
  font-family: 'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 500;
}
.mono { font-family: 'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace; }
a { color: inherit; }

.wrap { max-width: 860px; margin: 0 auto; padding: 0 32px; }

header.nav {
  position: sticky; top: 0; z-index: 100;
  backdrop-filter: blur(10px) saturate(1.1);
  -webkit-backdrop-filter: blur(10px) saturate(1.1);
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  border-bottom: 1px solid var(--border);
}
.nav-inner {
  max-width: 1160px; margin: 0 auto; padding: 16px 32px;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
/* 2026-09-12 (further follow-up): the raw marble-photo thumbnail here didn't hold up at 26px or
   against a dark theme, so it's replaced with the same flat-vector cube mark used for the
   favicon and section icons (black cube, moss-green top, per-page accent side), resolving the
   small-scale-legibility gap KC flagged earlier the same day. Sized via width/height on the svg
   itself, set inline where that markup is rendered further down, not via this class. */
.brand-mark {
  width: 28px; height: 28px; flex: none; color: var(--text-muted);
}
.brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.brand-word {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.92rem; font-weight: 700;
  font-style: italic; letter-spacing: 0.06em; color: #000;
}
.brand-word span { color: var(--accent); font-weight: 700; font-style: normal; }
/* Brand-name mentions in running body copy (see brand_style() in the generator): the "Black"
   half renders bold and italic, the "Tor" half bold and in the page's own accent colour,
   matching the nav wordmark above. "Black" is pinned to true black/white (not the themed
   --text colour) per KC's request, so it always reads as a literal black-on-light /
   white-on-dark word rather than the theme's off-black or cream text tone. */
.brand-black { font-weight: 700; font-style: italic; color: #000; }
.brand-tor { font-weight: 700; font-style: normal; color: var(--accent); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-word,
  :root:not([data-theme="light"]) .brand-black { color: #fff; }
}
:root[data-theme="dark"] .brand-word,
:root[data-theme="dark"] .brand-black { color: #fff; }
.brand-suffix {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.6rem; font-weight: 400;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-faint);
}
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.links { display: flex; align-items: center; gap: 28px; list-style: none; margin: 0; padding: 0; }
.links li { display: flex; align-items: center; }
.links a {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; letter-spacing: 0.04em;
  text-decoration: none; color: var(--text-muted);
  padding-bottom: 4px; border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.links a:hover, .links a.active { color: var(--accent); border-color: var(--accent); }
.links a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* per-site colour on nav/footer links: specificity raised to beat the generic rules above */
.links a[data-c="lichen"]:hover, .links a[data-c="lichen"].active,
.footer-links a[data-c="lichen"]:hover { color: var(--c-lichen); }
.links a[data-c="gorse"]:hover, .links a[data-c="gorse"].active,
.footer-links a[data-c="gorse"]:hover { color: var(--c-gorse); }
.links a[data-c="heather"]:hover, .links a[data-c="heather"].active,
.footer-links a[data-c="heather"]:hover { color: var(--c-heather); }
.links a[data-c="quartz"]:hover, .links a[data-c="quartz"].active,
.footer-links a[data-c="quartz"]:hover { color: var(--c-quartz); }
.links a[data-c="peat"]:hover, .links a[data-c="peat"].active,
.footer-links a[data-c="peat"]:hover { color: var(--c-peat); }
/* TTRPG page's own "Systems" dropdown (D&D / Forge / Tools) -- see the nav special-case below */
.links a[data-c="dnd"]:hover, .links a[data-c="dnd"].active { color: var(--c-dnd); }
.links a[data-c="forge"]:hover, .links a[data-c="forge"].active { color: var(--c-forge); }
.links a[data-c="tools"]:hover, .links a[data-c="tools"].active { color: var(--c-tools); }
.links a[data-c]:hover, .links a[data-c].active { border-color: currentColor; }

/* 2026-09-12 (further): "Coding" dropdown grouping Excel/Python/SQL/XML/Data Analytics/VBA
   under one nav tab, per KC's requested menu restructure (Home / Coding / About / Contact).
   Hover and focus-within open it on desktop; a small script toggles an .open class for touch
   and click support, and closes it on an outside click or Escape. The existing per-colour
   .links a[data-c="..."] hover/active rules above already apply to the menu's links too, since
   they use a descendant selector rather than a direct-child one. */
.nav-dropdown { position: relative; display: flex; align-items: center; }
.nav-dropdown-toggle {
  font: inherit; line-height: inherit;
  -webkit-appearance: none; appearance: none;
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; letter-spacing: 0.04em;
  text-decoration: none; color: var(--text-muted); background: none; border: none;
  cursor: pointer; padding: 0 0 4px; margin: 0; display: flex; align-items: center; gap: 5px;
  border-bottom: 1px solid transparent; transition: color 0.15s ease, border-color 0.15s ease;
}
.nav-dropdown-toggle:hover, .nav-dropdown-toggle.active, .nav-dropdown-toggle[aria-expanded="true"] {
  color: var(--accent); border-color: var(--accent);
}
.nav-dropdown-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.nav-dropdown-toggle .chevron { width: 8px; height: 8px; flex: none; transition: transform 0.15s ease; }
.nav-dropdown:hover .chevron, .nav-dropdown.open .chevron, .nav-dropdown-toggle[aria-expanded="true"] .chevron {
  transform: rotate(180deg);
}
.nav-dropdown-menu {
  position: absolute; top: 100%; left: 0; margin: 12px 0 0; padding: 8px;
  list-style: none; min-width: 172px; display: none; flex-direction: column; gap: 2px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 14px 32px rgba(0,0,0,0.2); z-index: 50;
}
/* Bridges the 12px margin-top gap above so the pointer never leaves a hoverable descendant
   of .nav-dropdown while travelling from the toggle button down into the menu - otherwise
   the CSS :hover this menu depends on is lost mid-transit and the menu closes before it can
   be reached. Transparent, so it has no visual effect. */
.nav-dropdown-menu::before {
  content: ''; position: absolute; top: -12px; left: 0; right: 0; height: 12px;
  background: transparent;
}
.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown:focus-within .nav-dropdown-menu,
.nav-dropdown.open .nav-dropdown-menu { display: flex; }
.nav-dropdown-menu a {
  display: block; padding: 6px 10px; border-radius: 6px; border-bottom: none !important;
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; letter-spacing: 0.04em;
  text-decoration: none; color: var(--text-muted); transition: color 0.15s ease, background 0.15s ease;
}
.nav-dropdown-menu a:hover, .nav-dropdown-menu a.active { background: var(--bg); }

/* 2026-09-17: secondary nav row, direction D from the nav-options mockups. Sits directly under
   the main .nav-inner bar, inside the same sticky header, on EVERY page now, not only ones with
   a family of sub-pages -- an empty <div class="nav-secondary-inner"></div> is still rendered on
   pages with nothing to show there (see the generator), so this row's fixed height (padding +
   min-height below) holds the hero/intro content at an identical vertical position on every page
   regardless of whether the row itself has links in it. Right-aligned per KC's request, so it
   reads as a secondary/lesser action row under the primary nav rather than competing with it.
   Colour: unstyled links use the neutral --text-muted token like the rest of the site's link
   system; hover/active pick up var(--accent), which already resolves to each page's own accent
   colour (moss on Excel/Lookups/Lists, quartz on XML, etc.), so no per-page override is needed
   here specifically for that. Only Excel/Lookups/Lists populate it today (Lookups, Lists --
   Excel itself is left out, since restating the page family you're already in was redundant with
   the main "Coding" dropdown already showing Excel active); see FAMILY_CHILDREN in the
   generator for where this is set. */
.nav-secondary {
  border-top: 1px solid var(--border); background: var(--bg-sunken);
}
.nav-secondary-inner {
  max-width: 1160px; margin: 0 auto; padding: 9px 32px;
  display: flex; align-items: center; justify-content: flex-end; gap: 22px; flex-wrap: wrap;
  min-height: 19px;
}
.nav-secondary a {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.74rem; letter-spacing: 0.04em;
  text-decoration: none; color: var(--text-muted);
  padding-bottom: 2px; border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.nav-secondary a:hover, .nav-secondary a.active { color: var(--accent); border-color: var(--accent); }
.nav-secondary a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.hero-solo { padding: 64px 0 8px; }
.hero-solo .eyebrow { display: block; margin-bottom: 10px; }
.hero-solo h1 { font-size: clamp(2.1rem, 4.4vw, 3rem); line-height: 1.1; margin: 0 0 18px; }
.hero-solo p.lede { color: var(--text-muted); font-size: 1.05rem; max-width: 62ch; margin: 0; }

/* 2026-09-12 (further follow-up): hero image, matching the home page's specimen treatment and
   position (beside the title/intro), added to every other page. Scaled down to fit the
   narrower 860px prose column these pages use (versus home's 1160px), rather than widening
   that column just for this. */
.hero-solo-grid { display: grid; grid-template-columns: minmax(0, 1fr) 200px; gap: 32px; align-items: center; }
.hero-solo-copy { min-width: 0; }
.specimen { animation: rise 0.7s ease-out both; }
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
/* 2026-09-13: no card chrome here any more -- the artwork's edges are transparent (KC's own
   words: "there should be no surround to the image"), so the frame's background/border/
   border-radius/box-shadow/padding were dropped and the image is shown directly, in both
   colour schemes. */
.specimen-frame img { display: block; width: 100%; height: auto; }
.specimen-cap {
  display: flex; justify-content: space-between; align-items: baseline; margin-top: 10px;
  padding: 0 2px; font-family: 'IBM Plex Mono', monospace; font-size: 0.6rem;
  letter-spacing: 0.05em; color: var(--text-faint); text-transform: uppercase;
}
.specimen-cap b { color: var(--text-muted); font-weight: 500; }
/* Dark mode swaps to the glow presentation, same as home -- the artwork already bakes in its
   own tint/glow, so no separate cutout mask is needed. */
.specimen-glow-wrap { display: none; padding: 10px 0; }
.specimen-cutout {
  display: block; width: 100%; height: auto;
  filter:
    drop-shadow(0 0 16px rgba(var(--specimen-glow-rgb), 0.55))
    drop-shadow(0 0 50px rgba(var(--specimen-glow-rgb), 0.4))
    drop-shadow(0 0 100px rgba(var(--specimen-glow-rgb), 0.25));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .specimen-frame--light { display: none; }
  :root:not([data-theme="light"]) .specimen-glow-wrap { display: block; }
}
:root[data-theme="dark"] .specimen-frame--light { display: none; }
:root[data-theme="dark"] .specimen-glow-wrap { display: block; }
@media (max-width: 700px) {
  .hero-solo-grid { grid-template-columns: 1fr; }
  .hero-solo-copy { order: 2; }
  .specimen { order: 1; max-width: 240px; margin: 0 auto; }
}

.prose a, .lede a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover, .lede a:hover { color: var(--accent-strong); }

.notice, .status-panel {
  margin: 40px 0; padding: 22px 26px; border: 1px solid var(--border); border-radius: 8px;
}
.notice { background: var(--bg-elevated); }
.status-panel { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); }
.notice-eyebrow {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 500; display: block; margin-bottom: 10px;
}
.status-panel .notice-eyebrow { color: var(--accent-strong); }
/* Contact page "Contact details" panel heading: KC asked for this specific header to render
   larger than the standard small-caps eyebrow style, sized one point above the site's normal
   (body) text size rather than relative to the eyebrow's own smaller base size. */
.contact-details-eyebrow { font-size: calc(1rem + 1pt); }
.notice h3, .status-panel h3 { font-size: 1.05rem; margin-bottom: 8px; }
.notice p, .status-panel p { color: var(--text-muted); font-size: 0.92rem; margin: 0; }
.status-panel p { color: var(--text); }
.status-panel p b { color: var(--accent-strong); font-weight: 600; }

.examples-head { margin: 60px 0 28px; }
.examples-head .eyebrow { display: block; margin-bottom: 8px; }
.examples-head h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin-bottom: 10px; }
.examples-head p { color: var(--text-muted); margin: 0; }

/* ---------- PAGE GRID (main content + sidebar of practical notes) ---------- */
.wrap-wide { max-width: 1160px; margin: 0 auto; padding: 0 32px; }
.page-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 48px; align-items: start; }
.page-main { min-width: 0; }
.page-side {
  position: sticky; top: 96px;
  border-left: 1px solid var(--border);
  padding-left: 32px;
}
.side-head { margin-bottom: 20px; }
.side-head .eyebrow { display: block; margin-bottom: 6px; }
.side-head h3 { font-size: 1.05rem; margin-bottom: 6px; }
.side-head p { color: var(--text-muted); font-size: 0.82rem; margin: 0; }
.tip-list { display: flex; flex-direction: column; }
.tip { padding: 16px 0; border-top: 1px solid var(--border); }
.tip:first-child { padding-top: 0; border-top: none; }
.tip-date {
  display: block; font-family: 'IBM Plex Mono', monospace; font-size: 0.64rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 6px;
}
.tip h4 {
  font-family: 'IBM Plex Serif', Georgia, serif; font-weight: 600; letter-spacing: -0.005em;
  font-size: 0.92rem; margin: 0 0 6px; color: var(--text);
}
.tip h4 a { color: inherit; text-decoration: none; }
.tip h4 a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.tip p { color: var(--text-muted); font-size: 0.85rem; margin: 0; }
@media (max-width: 900px) {
  .page-grid { grid-template-columns: 1fr; }
  .page-side {
    position: static; border-left: none; padding-left: 0;
    margin-top: 20px; padding-top: 32px; border-top: 1px solid var(--border);
  }
}

.example {
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated);
  padding: 28px 28px 26px; margin-bottom: 20px;
}
.example p { margin: 0 0 12px; font-size: 0.95rem; color: var(--text-muted); }
.example p:last-child { margin-bottom: 0; }
.example p b { font-weight: 600; }
.example-snippet {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; color: var(--accent-strong);
  background: var(--accent-soft); border-radius: 4px; padding: 9px 11px; margin: 0 0 14px;
  white-space: pre-wrap; word-break: break-word; line-height: 1.55;
}
/* VBA-only: real, runnable code in "A few examples" reads as code, not prose, same reasoning
   as the Courier New treatment on the Practical routines section further down this page. */
.page-vba .example-snippet {
  font-family: 'Courier New', Courier, monospace; font-size: 0.84rem;
}

/* ---------- FORMULAS EXPLAINED (Excel page only, for now) ---------- */
.formula-block {
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated);
  padding: 28px 28px 26px; margin-bottom: 20px;
}
.formula-block h4 { font-size: 1rem; margin-bottom: 12px; }
.formula-code {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; color: var(--accent-strong);
  background: var(--accent-soft); border-radius: 4px; padding: 12px 14px; margin: 0 0 14px;
  white-space: pre-wrap; word-break: break-word; line-height: 1.5;
}
.formula-block p { color: var(--text-muted); font-size: 0.92rem; margin: 0; }

/* ---------- PRACTICAL ROUTINES / QUERIES / DATA RETRIEVAL (VBA, SQL and Python pages).
   Code is deliberately set in Courier New rather than the site's usual IBM Plex Mono, so a
   runnable routine, query or script reads as visually distinct from the descriptive prose
   around it. The section eyebrow label varies per page (see routines_label). ---------- */
.routine-block {
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated);
  padding: 28px 28px 26px; margin-bottom: 20px;
}
.routine-kind {
  display: inline-block; font-family: 'IBM Plex Mono', monospace; font-size: 0.66rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-strong);
  background: var(--accent-soft); border-radius: 3px; padding: 3px 9px; margin-bottom: 14px;
}
.routine-block h4 { font-size: 1rem; margin-bottom: 12px; }
.routine-code {
  font-family: 'Courier New', Courier, monospace; font-size: 0.84rem; color: var(--accent-strong);
  background: var(--accent-soft); border-radius: 4px; padding: 14px 16px; margin: 0 0 14px;
  white-space: pre-wrap; word-break: break-word; line-height: 1.55;
}
.routine-block p { color: var(--text-muted); font-size: 0.92rem; margin: 0; }

/* ---------- NOTES IN FULL (expanded version of each sidebar tip) ---------- */
.note-full { padding: 30px 0; border-top: 1px solid var(--border); scroll-margin-top: 24px; }
.note-full:first-child { padding-top: 0; border-top: none; }
.note-full-date {
  display: block; font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 8px;
}
.note-full h3 { font-size: 1.15rem; margin-bottom: 12px; }
.note-full p { margin: 0 0 12px; font-size: 0.95rem; color: var(--text-muted); }
.note-full p:last-of-type { margin-bottom: 0; }
/* 2026-09-12 (further): a "Top" link with an up arrow sits on the right of the same row as
   "Back to Recent notes", per KC's request for an extra navigation aid on each full article. */
.note-full-links {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px;
}
.note-full-back {
  display: inline-block; font-family: 'IBM Plex Mono', monospace;
  font-size: 0.76rem; color: var(--accent); text-decoration: none;
}
.note-full-back:hover { text-decoration: underline; text-underline-offset: 2px; }
.note-full-top {
  display: inline-block; font-family: 'IBM Plex Mono', monospace;
  font-size: 0.76rem; color: var(--text-muted); text-decoration: none;
}
.note-full-top:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

.tag-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.tag {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.66rem; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 3px 9px; border-radius: 3px; font-weight: 500;
}
.tag--excel { background: var(--c-moss-soft); color: var(--c-moss-strong); }
.tag--xml { background: var(--c-quartz-soft); color: var(--c-quartz-strong); }
.tag--vba { background: var(--c-lichen-soft); color: var(--c-lichen-strong); }
.tag--sql { background: var(--c-gorse-soft); color: var(--c-gorse-strong); }
.tag--python { background: var(--c-heather-soft); color: var(--c-heather-strong); }
.tag--docs { background: var(--border); color: var(--text-muted); }

.form-field { margin-bottom: 20px; }
.form-field:last-child { margin-bottom: 0; }
.form-label {
  display: block; font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 500; margin-bottom: 8px;
}
.form-input, .form-textarea {
  width: 100%; font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 0.95rem;
  color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 11px 13px; transition: border-color 0.15s ease; box-sizing: border-box;
}
.form-input:focus, .form-textarea:focus { outline: none; border-color: var(--accent); }
.form-textarea { resize: vertical; min-height: 120px; font-family: inherit; }
.form-choices { display: flex; flex-wrap: wrap; gap: 10px; }
.form-choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.form-choice label {
  display: inline-block; font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; letter-spacing: 0.03em;
  color: var(--text-muted); border: 1px solid var(--border); border-radius: 5px; padding: 8px 14px;
  cursor: pointer; transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.form-choice input:checked + label {
  border-color: var(--accent); color: var(--accent-strong); background: var(--accent-soft);
}
/* Per-enquiry-type colour on the Contact page's chooser: when a chip is selected, its outline
   (border) matches that discipline's own site-wide accent colour rather than one generic
   active colour, per KC's request. Excel and Access intentionally keep the page's own moss
   accent (the default rule above), matching the "Legacy system rescue" section's existing
   convention of pairing Excel + Access under moss; SQL/Python/TTRPG get their own hue via a
   data-c attribute on the chip, mirroring the nav/footer link colouring pattern above. */
.form-choice[data-c="gorse"] input:checked + label { border-color: var(--c-gorse); color: var(--c-gorse-strong); background: var(--c-gorse-soft); }
.form-choice[data-c="heather"] input:checked + label { border-color: var(--c-heather); color: var(--c-heather-strong); background: var(--c-heather-soft); }
.form-choice[data-c="leat"] input:checked + label { border-color: var(--c-leat); color: var(--c-leat-strong); background: var(--c-leat-soft); }
.form-choice input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }
.form-submit {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.82rem; letter-spacing: 0.04em;
  color: var(--bg-elevated); background: var(--accent); border: none; border-radius: 6px;
  padding: 12px 22px; cursor: pointer; transition: background 0.15s ease;
}
.form-submit:hover { background: var(--accent-strong); }
.form-note { font-size: 0.82rem; color: var(--text-faint); margin: 12px 0 0; max-width: none; }
.form-status { font-size: 0.82rem; color: var(--accent-strong); margin: 12px 0 0; display: none; }
.form-status.visible { display: block; }

footer {
  border-top: 1px solid var(--border); background: var(--bg-sunken);
  position: relative; overflow: hidden; margin-top: 64px;
}
.footer-watermark {
  position: absolute; right: -40px; bottom: -80px; width: 340px; height: 340px;
  object-fit: cover; opacity: 0.09; filter: grayscale(1) contrast(0.9);
  -webkit-mask-image: radial-gradient(circle at 62% 42%, black, transparent 68%);
  mask-image: radial-gradient(circle at 62% 42%, black, transparent 68%);
  pointer-events: none;
}
.footer-inner {
  max-width: 1160px; margin: 0 auto; padding: 52px 32px 28px;
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 30px;
}
.footer-top {
  display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 28px;
}
.footer-brand h3 { font-size: 1.1rem; margin-bottom: 6px; }
.footer-brand p { color: var(--text-muted); font-size: 0.86rem; max-width: 34ch; margin: 0; }
.footer-links {
  display: flex; gap: 20px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap;
}
.footer-links a {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.76rem; color: var(--text-muted);
  text-decoration: none;
}
.footer-links a:hover { color: var(--accent); }
.footer-aside {
  padding-top: 18px; border-top: 1px solid var(--border);
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;
}
.footer-aside .also { font-size: 0.78rem; color: var(--text-faint); text-decoration: none; }
.footer-aside .also::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 8px;
  border-radius: 50%; background: var(--c-leat); vertical-align: middle;
}
.footer-aside .also:hover { color: var(--c-leat); }
.footer-aside .copy { font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; color: var(--text-faint); }

/* ---------- TTRPG page: preview-card grid, ported directly from the Home page's own
   .card/.card-grid system (same class names, same structure) so each preview reads exactly
   like Home's "Excel Formulae" etc. cards -- domain + coloured dot, status pill, title, a
   snippet-style line, an update line, and a link out once each has a real page of its own.
   --card-accent/-strong/-soft default to this page's own accent (leat blue); per-system
   modifiers below override them, matching Home's .card--xml/--vba/etc. pattern. */
.card-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 980px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .card-grid { grid-template-columns: 1fr; } }
.card {
  min-width: 0; scroll-margin-top: 96px;
  --card-accent: var(--accent); --card-accent-strong: var(--accent-strong); --card-accent-soft: var(--accent-soft);
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 8px;
  padding: 26px 26px 24px; display: flex; flex-direction: column; gap: 14px;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
.card--dnd { --card-accent: var(--c-dnd); --card-accent-strong: var(--c-dnd-strong); --card-accent-soft: var(--c-dnd-soft); }
.card--forge { --card-accent: var(--c-forge); --card-accent-strong: var(--c-forge-strong); --card-accent-soft: var(--c-forge-soft); }
.card--tools { --card-accent: var(--c-tools); --card-accent-strong: var(--c-tools-strong); --card-accent-soft: var(--c-tools-soft); }
.card:hover { border-color: color-mix(in srgb, var(--card-accent) 35%, var(--border-strong)); transform: translateY(-2px); }
.card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.card-domain {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.74rem; color: var(--text-faint); letter-spacing: 0.02em;
  overflow-wrap: break-word; word-break: break-word; min-width: 0;
}
.card-domain::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 8px;
  border-radius: 50%; background: var(--card-accent); vertical-align: middle;
}
.status {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.62rem; letter-spacing: 0.09em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 3px; font-weight: 500; white-space: nowrap;
}
.status.live { background: var(--card-accent-soft); color: var(--card-accent-strong); }
.status.build { background: var(--status-build-bg); color: var(--status-build-text); }
.card h3 { font-size: 1.5rem; }
.card-snippet {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem; color: var(--card-accent-strong);
  background: var(--card-accent-soft); border-radius: 4px; padding: 9px 11px; white-space: pre-wrap; word-break: break-word;
}
.card-update { font-size: 0.93rem; color: var(--text); margin: 0; }
.card-update b { font-weight: 600; color: var(--text); }
.card-link {
  margin-top: auto; padding-top: 6px; font-family: 'IBM Plex Mono', monospace; font-size: 0.78rem;
  color: var(--card-accent); text-decoration: none; display: inline-flex; align-items: center; gap: 6px; width: fit-content;
}
.card-link:hover { color: var(--card-accent-strong); text-decoration: underline; }
/* No real destination yet for any TTRPG preview (see the "hub only, for now" note in
   landing-page.md) -- styled visibly inert (muted colour, no pointer events) rather than a
   clickable-looking dead link, per the lesson from the earlier footer-link bug. */
.card-link.muted { color: var(--text-faint); pointer-events: none; }
.ttrpg-legacy { border-top: 1px solid var(--border); padding-top: 40px; margin-top: 8px; }
.hero-tags { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; }
.hero-tags a {
  font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; letter-spacing: 0.08em;
  text-decoration: none; color: var(--text-muted); border: 1px solid var(--border);
  padding: 7px 12px; border-radius: 4px;
}
.hero-tags a:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.hero-tags a[data-c]:hover { border-color: currentColor; background: color-mix(in srgb, currentColor 12%, transparent); }
.hero-tags a[data-c="dnd"]:hover { color: var(--c-dnd); }
.hero-tags a[data-c="forge"]:hover { color: var(--c-forge); }
.hero-tags a[data-c="tools"]:hover { color: var(--c-tools); }

@media (max-width: 640px) {
  .wrap, .wrap-wide, .nav-inner, .footer-inner { padding-left: 20px; padding-right: 20px; }
  /* 2026-09-14 (further follow-up): the top bar grew from 5 items to 10 with the move to a
     flat, always-visible nav (direction D) -- on a phone width that no longer fits, so this
     row scrolls horizontally instead of clipping. The scrollbar itself is hidden (still
     reachable by touch/trackpad drag) to keep the bar visually quiet, matching the site's
     plain, unchromed nav style. */
  .links {
    overflow-x: auto; flex-wrap: nowrap; gap: 20px;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px;
  }
  .links::-webkit-scrollbar { display: none; }
  .links li { flex: none; }
}
