/* site.css — shared structural styles for every public site.
   All look-and-feel comes from the CSS variables each theme preset defines:

   --bg --surface --text --muted --accent --accent-contrast --border
   --font-body --font-heading --radius --header-bg --header-text
*/

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.68;
  font-size: 1.05rem;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle at top, rgba(255, 255, 255, 0.05), transparent 28%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 18%);
  opacity: 0.7;
}

h1, h2, h3, h4 { font-family: var(--font-heading); line-height: 1.15; color: var(--text); }
a { color: var(--accent); }
img { max-width: 100%; height: auto; }

/* ── Icons (inline SVG sprite, see partials/icon_sprite.html) ─────────── */
.icon { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: -0.15em; flex-shrink: 0; }

.container { position: relative; z-index: 1; max-width: 1100px; margin: 0 auto; padding: 0 1.25rem; }

/* ── Header ─────────────────────────────────────────────────────────────
   Sized to be looked past. It was a 5rem logo inside 1.05rem of padding, then
   a search form and a wrapping row of nav pills — on a phone, roughly half the
   viewport before any content; on desktop, a wasted band.

   The cost is vertical, so that is what is cut: the logo, the vertical padding
   and — the one that actually made it tall — the ROW gap. These items wrap
   onto two or three lines, and a symmetric `gap` paid the same generous space
   between the rows as between the items. Row and column gaps are now set
   separately, and the row gap is small.

   Below 820px the search form and nav collapse behind the hamburger. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--header-bg);
  border-bottom: 1px solid var(--border);
  backdrop-filter: blur(14px);
}
.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 0.25rem;
  column-gap: 0.9rem;
  padding: 0.4rem 1.25rem;
}
.site-brand { text-decoration: none; display: flex; align-items: center; gap: 0.55rem; min-width: 0; }
.site-brand-text { display: flex; flex-direction: column; min-width: 0; }
.site-logo { height: 2.4rem; width: auto; border-radius: calc(var(--radius) / 2); }
.site-title { font-family: var(--font-heading); font-size: 1.15rem; font-weight: 700; color: var(--header-text); line-height: 1.25; }
.site-tagline { font-size: 0.72rem; color: var(--muted); line-height: 1.2; }
.site-nav { margin-left: auto; display: flex; flex-wrap: wrap; row-gap: 0.15rem; column-gap: 0.25rem; align-items: center; }
.site-nav a {
  color: var(--header-text);
  text-decoration: none;
  font-size: 0.88rem;
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  transition: background-color 0.18s ease, color 0.18s ease;
}
.site-nav a:hover {
  color: var(--accent-contrast);
  background: var(--accent);
}
.search-form { display: flex; align-items: center; gap: 0.35rem; }
.search-form .input { padding: 0.3rem 0.65rem; font-size: 0.85rem; width: 10rem; }
.search-form .btn { padding: 0.3rem 0.6rem; }

/* ── The hamburger ──────────────────────────────────────────────────────
   A checkbox, not a script. The previous version toggled a class from
   JavaScript and shipped a control that rendered, looked interactive, and did
   nothing — a failure mode a checkbox does not have, because the browser
   toggles :checked itself.

   The reveal below uses `~`, so .nav-checkbox must come BEFORE .search-form
   and .site-nav in the markup. See macros/header.html. */
.nav-checkbox {
  /* Clipped, never display:none — that would drop it out of the tab order and
     make the menu unreachable by keyboard. This keeps Space working. */
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.nav-toggle {
  display: none;
  margin-left: auto;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  background: transparent;
  color: var(--header-text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.nav-toggle-bars { position: relative; }
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 1.15rem;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}
.nav-toggle-bars::before,
.nav-toggle-bars::after { content: ''; position: absolute; left: 0; }
.nav-toggle-bars::before { top: -6px; }
.nav-toggle-bars::after { top: 6px; }
.nav-checkbox:checked + .nav-toggle {
  background: var(--accent);
  color: var(--accent-contrast);
  border-color: var(--accent);
}
/* The checkbox is invisible, so its focus ring has to be drawn on the label. */
.nav-checkbox:focus-visible + .nav-toggle {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 820px) {
  /* Already in <title> and the meta description; in a collapsed header it is
     the first thing worth its row back. */
  .site-tagline { display: none; }

  .nav-toggle { display: inline-flex; }
  .search-form,
  .site-nav { display: none; }

  /* Open: a panel under the header, not a second row of pills. Full-width
     stacked rows with real tap targets — what a mobile menu looks like
     everywhere else. The header grows to hold it rather than the panel
     overlaying the page: an overlay needs a stacking context and a scroll
     lock to behave, and neither is worth it for a list of six links. */
  .nav-checkbox:checked ~ .search-form,
  .nav-checkbox:checked ~ .site-nav {
    display: flex;
    flex-basis: 100%;
    margin-left: 0;
  }
  .nav-checkbox:checked ~ .search-form {
    order: 1;
    padding-top: 0.5rem;
  }
  .nav-checkbox:checked ~ .search-form .input { flex: 1; width: auto; }

  .nav-checkbox:checked ~ .site-nav {
    order: 2;
    flex-direction: column;
    align-items: stretch;
    row-gap: 0;
    padding: 0.4rem 0 0.2rem;
    border-top: 1px solid var(--border);
    margin-top: 0.5rem;
  }
  .nav-checkbox:checked ~ .site-nav a {
    padding: 0.65rem 0.5rem;
    font-size: 0.98rem;
    border-radius: var(--radius);
  }
  /* The cross-site links are outlined pills at desktop width; as full-width
     rows that outline reads as a text field, so it becomes a rule instead. */
  .nav-checkbox:checked ~ .site-nav .fleet-link {
    border: none;
    border-top: 1px solid var(--border);
    border-radius: 0;
  }
}

/* ── Fleet cross-links (macros/fleet.html) ──────────────────────────────
   A link to a sibling site leaves this hostname, so it is drawn differently
   from the site's own nav. Outlined rather than louder: it should read as a
   way across, not as the most important thing in the header. */
.site-nav .fleet-link {
  border: 1px solid var(--accent);
  color: var(--accent);
}
.site-nav .fleet-link:hover {
  background: var(--accent);
  color: var(--accent-contrast);
}

.related-guides { margin-top: 2.5rem; }
.guide-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; }
.guide-item {
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius, 8px);
  background: var(--surface);
}
.guide-link { font-weight: 600; text-decoration: none; color: var(--text); }
.guide-link:hover { color: var(--accent); text-decoration: underline; }
.guide-summary { margin: 0.3rem 0 0; font-size: 0.9rem; color: var(--muted); }

/* ── Hero ───────────────────────────────────────────────────────────────
   The image sits beside the headline, not above it. Full-bleed at 18/8 it was
   about 490px tall on an 1100px page, so the entire first screen was one
   article's photograph and the grid of everything else began below the fold.
   A thumbnail still tells you the lead has a picture; it just stops being the
   page. .hero-link-media is set by the template only when there is an image —
   without it the single text child would be laid into the image column. */
.hero { margin: 1.5rem 0 2rem; }
.hero-link {
  display: grid;
  gap: 1rem;
  padding: 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 10px);
  text-decoration: none;
  color: inherit;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.07);
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.hero-link-media {
  grid-template-columns: 9rem minmax(0, 1fr);
  align-items: center;
  gap: 1.1rem;
}
.hero-link:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 44px rgba(0, 0, 0, 0.1);
  border-color: var(--accent);
}
/* A hard ceiling in absolute units, not only a ratio. An aspect-ratio alone
   still scales with the column, which is how this stayed overpowering after
   being "made smaller" once already. max-height means it cannot dominate the
   page whatever the column does. */
.hero-image {
  width: 100%;
  max-width: 9rem;
  max-height: 7rem;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
}
.hero-text { padding: 0.15rem 0.3rem 0.3rem; min-width: 0; }
.hero-title { font-size: clamp(1.45rem, 2.6vw, 2.05rem); margin: 0.4rem 0 0.4rem; letter-spacing: -0.02em; }
.hero-excerpt { color: var(--muted); font-size: 1rem; margin: 0; max-width: 68ch; }
.hero-empty {
  text-align: center;
  padding: 2.5rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 10px);
}

@media (max-width: 720px) {
  /* Still side by side on a phone, just narrower. Stacking it put a
     full-width image back above the headline, which is the thing being
     removed. */
  .hero-link-media { grid-template-columns: 6.5rem minmax(0, 1fr); gap: 0.9rem; }
  .hero-image { max-width: 6.5rem; max-height: 5rem; }
  .hero-link { padding: 0.8rem; }
}

/* ── Home: content column + skim rail ───────────────────────────────────
   The rail is titles only and holds articles that are not already in the grid
   below it, so it adds reach rather than repeating what is on screen. It
   collapses to a normal block under the aside breakpoint — sticky positioning
   is dropped there too, or it would pin mid-scroll on a phone. */
/* One column by default. The second is added by .home-layout-rail, which the
   template sets only when there is a rail — the column used to be
   unconditional while the rail was not, so a site without one rendered its
   content off-centre beside a blank 16rem strip. */
.home-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2.25rem;
  align-items: start;
}
.home-layout-rail { grid-template-columns: minmax(0, 1fr) 16rem; }
.home-main { min-width: 0; }
.home-aside { position: sticky; top: 5.5rem; }
.aside-heading {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  margin: 0 0 0.5rem;
}
.aside-list { list-style: none; margin: 0; padding: 0; }
.aside-list li + li { border-top: 1px solid var(--border); }
.aside-list a {
  display: block;
  padding: 0.6rem 0;
  color: var(--text);
  text-decoration: none;
  font-size: 0.92rem;
  line-height: 1.42;
}
.aside-list a:hover { color: var(--accent); }
.aside-meta { display: block; font-size: 0.74rem; color: var(--muted); margin-top: 0.15rem; }

@media (max-width: 980px) {
  .home-layout,
  .home-layout-rail { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
  .home-aside { position: static; }
}

/* ── Cards ──────────────────────────────────────────────────────────── */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.6rem; margin: 2rem 0; }
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 8px);
  overflow: hidden;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.08);
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 22px 48px rgba(0, 0, 0, 0.12);
  border-color: var(--accent);
}
.card-link { display: flex; flex-direction: column; min-height: 100%; text-decoration: none; color: inherit; }
.card-image { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; filter: saturate(1.03) contrast(1.02); }
.card-image-placeholder { background: linear-gradient(135deg, var(--accent), var(--surface)); aspect-ratio: 16 / 10; display: flex; align-items: center; justify-content: center; }
.card-image-placeholder .icon { width: 2.25rem; height: 2.25rem; color: var(--accent-contrast); opacity: 0.65; }
.card-body { padding: 1rem 1.1rem 1.25rem; display: flex; flex-direction: column; gap: 0.4rem; flex: 1; }
.card-category { display: inline-flex; align-items: center; gap: 0.3rem; width: fit-content; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); text-decoration: none; margin-bottom: 0.15rem; }
.card-title { margin: 0.1rem 0 0.2rem; font-size: 1.14rem; }
.card-excerpt { color: var(--muted); font-size: 0.92rem; margin: 0; }
.card-meta { display: flex; gap: 0.75rem; flex-wrap: wrap; font-size: 0.8rem; color: var(--muted); margin-top: auto; padding-top: 0.25rem; }
.card-meta span, .card-meta time { display: inline-flex; align-items: center; gap: 0.3rem; }

/* ── Article ────────────────────────────────────────────────────────── */
.article-narrow { max-width: 860px; margin: 2rem auto; }
.article-full { width: 100%; }
.article {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 10px);
  padding: clamp(1.1rem, 2vw, 1.75rem);
  box-shadow: 0 22px 54px rgba(0, 0, 0, 0.08);
}
.article-header { margin-bottom: 1.4rem; }
.article-title { font-size: clamp(1.8rem, 3.6vw, 2.6rem); margin: 0.35rem 0 0.85rem; letter-spacing: -0.02em; }
.article-hero { margin: 0 0 1.5rem; }
.article-hero img {
  width: 100%;
  border-radius: calc(var(--radius) + 6px);
  aspect-ratio: 16 / 9;
  object-fit: cover;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.12);
}
.article-hero figcaption { font-size: 0.78rem; color: var(--muted); margin-top: 0.4rem; }
.article-hero figcaption a { color: var(--muted); }
.article-body { max-width: 70ch; }
.article-body h2 { margin-top: 2.2rem; }
.article-body h3 { margin-top: 1.6rem; }
.article-body p, .article-body li { font-size: 1.03rem; line-height: 1.74; }
.article-body pre { background: var(--surface); border: 1px solid var(--border); border-radius: calc(var(--radius) + 4px); padding: 1rem; overflow-x: auto; font-size: 0.9rem; }
.article-body code { background: var(--surface); padding: 0.1em 0.35em; border-radius: 4px; font-size: 0.92em; }
.article-body pre code { background: none; padding: 0; }
.article-body blockquote {
  border-left: 3px solid var(--accent);
  margin: 1.5rem 0;
  padding: 1rem 1.2rem;
  color: var(--muted);
  background: rgba(127, 127, 127, 0.06);
  border-radius: 0 calc(var(--radius) + 2px) calc(var(--radius) + 2px) 0;
}
.article-tags { margin: 1.5rem 0 0.5rem; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.tag {
  background: rgba(127, 127, 127, 0.08);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.22rem 0.8rem;
  font-size: 0.8rem;
  color: var(--muted);
}

/* ── Byline / author ────────────────────────────────────────────────── */
.avatar-fallback { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; border-radius: 50%; background: var(--surface); border: 1px solid var(--border); color: var(--muted); }
.avatar-fallback .icon { width: 50%; height: 50%; }
.byline { display: flex; align-items: center; gap: 0.75rem; padding: 0.85rem 0; }
.byline-avatar { border-radius: 50%; }
.byline-text { display: flex; flex-direction: column; font-size: 0.88rem; }
.byline-name { font-weight: 600; text-decoration: none; }
.byline-quals, .byline-date { color: var(--muted); font-size: 0.8rem; }
.author-box { background: var(--surface); border: 1px solid var(--border); border-radius: calc(var(--radius) + 8px); padding: 1.25rem; box-shadow: 0 14px 34px rgba(0, 0, 0, 0.08); }
.author-box img { border-radius: 50%; }
.author-box h3 { margin: 0.5rem 0 0.2rem; }
.author-box h3 a { text-decoration: none; color: var(--text); }
.author-quals { color: var(--accent); font-size: 0.85rem; margin: 0 0 0.5rem; }
.author-header { display: flex; gap: 1.5rem; align-items: center; }
.author-avatar { border-radius: 50%; }

/* ── Human contributors ─────────────────────────────────────────────────
   Structurally distinct from the persona byline above, not a restyle of it.
   The photo is a square-cropped photograph rather than a circular illustrated
   avatar, the byline carries a job title and credentials the persona has no
   truthful equivalent for, and only a person gets the .writer-box at the foot
   of an article. Colours come from theme variables like everything else. */
.writer-byline { align-items: flex-start; border-left: 3px solid var(--accent); padding-left: 0.9rem; }
.writer-photo { border-radius: var(--radius); object-fit: cover; flex-shrink: 0; }
.writer-name { color: var(--text); }
.writer-role { color: var(--accent); font-size: 0.85rem; font-weight: 600; margin: 0; }
.writer-credentials { color: var(--muted); font-size: 0.8rem; margin: 0; }
.writer-box { display: flex; gap: 1.25rem; align-items: flex-start; margin: 2.5rem 0 0; padding: 1.25rem; background: var(--surface); border: 1px solid var(--border); border-radius: calc(var(--radius) + 8px); }
.writer-box-name { margin: 0 0 0.2rem; font-size: 1.05rem; }
.writer-box-name a { color: var(--text); text-decoration: none; }
.writer-bio { font-size: 0.9rem; color: var(--text); }
.writer-bio p:last-child { margin-bottom: 0; }
.writer-links { list-style: none; display: flex; flex-wrap: wrap; gap: 0.9rem; padding: 0; margin: 0.6rem 0 0; font-size: 0.85rem; }
.writer-header { display: flex; gap: 1.75rem; align-items: flex-start; }
.writer-header h1 { margin: 0 0 0.35rem; }
.writer-header-photo { border-radius: var(--radius); }
.writer-header-text { max-width: 44rem; }

@media (max-width: 600px) {
  .writer-box, .writer-header { flex-direction: column; gap: 1rem; }
}

/* ── Listings / misc ────────────────────────────────────────────────── */
.listing-header { margin: 2.5rem 0 0.5rem; }
.listing-header p { color: var(--muted); }
.related h2 { margin-top: 3rem; }
.empty-note { color: var(--muted); }

/* ── Forms & buttons (search, newsletter, contact) ─────────────────── */
.form { display: grid; gap: 0.9rem; max-width: 480px; margin: 1.5rem 0; }
.field { display: grid; gap: 0.3rem; }
.field label { font-size: 0.85rem; color: var(--muted); }
.input, .textarea {
  font: inherit; padding: 0.6rem 0.85rem; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--bg); color: var(--text);
}
.textarea { resize: vertical; min-height: 6rem; }
.btn {
  display: inline-flex; align-items: center; gap: 0.4rem; justify-content: center;
  background: var(--accent); color: var(--accent-contrast); border: none;
  border-radius: 999px; padding: 0.55rem 1.15rem; font: inherit; font-weight: 600;
  cursor: pointer; text-decoration: none;
}
.btn:hover { filter: brightness(1.08); }
.form-banner { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 0.75rem 1rem; margin: 1rem 0; color: var(--text); }
.newsletter-form { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.newsletter-form .input { min-width: 14rem; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Off-screen to the eye, present to a screen reader. Distinct from .hp-field,
   which hides a honeypot from everyone including assistive tech. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Ads: reserve space so units don't shift the layout (CLS) ───────── */
.ad-slot { min-height: 100px; margin: 1.5rem auto; text-align: center; }
.ad-slot-header, .ad-slot-footer { max-width: 1100px; }
.ad-slot-sidebar { min-height: 250px; }
/* Reserve height for the in-flow placements too, or they shift the article
   when the unit loads — the CLS problem .ad-slot exists to prevent. */
.ad-slot-below_hero, .ad-slot-in_article { max-width: 860px; min-height: 280px; }

/* ── Footer ─────────────────────────────────────────────────────────── */
.site-footer { border-top: 1px solid var(--border); margin-top: 3rem; background: var(--header-bg); backdrop-filter: blur(14px); }
.footer-inner { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between; align-items: center; padding: 1.5rem 1.25rem; font-size: 0.85rem; color: var(--muted); }
.footer-preview-image { height: 7.8rem; width: auto; flex-shrink: 0; border-radius: calc(var(--radius) / 2); }
.footer-inner a { color: var(--muted); margin-right: 1rem; }
