/* ==========================================================================
   Blackstorm Security — design system
   Dark charcoal foundation + a single electric-cyan accent.
   Loaded after Tachyons/Ananke, so it intentionally overrides theme utilities.
   ========================================================================== */

:root {
  /* Surfaces */
  --bs-bg:            #0B0F14;
  --bs-bg-alt:        #0F1620;
  --bs-surface:       #131C26;
  --bs-surface-hi:    #1A2634;
  --bs-border:        #24313F;
  --bs-border-hi:     #33455A;

  /* Text */
  --bs-text:          #E6EDF3;
  --bs-text-soft:     #B7C3CF;
  --bs-muted:         #8494A3;

  /* Accent — electric storm cyan */
  --bs-accent:        #00C2FF;
  --bs-accent-hi:     #5AD8FF;
  --bs-accent-dim:    #0A6D8F;
  --bs-accent-glow:   rgba(0, 194, 255, 0.14);

  /* Type */
  --bs-font: "IBM Plex Sans", "Inter", -apple-system, BlinkMacSystemFont,
             "Segoe UI", "Avenir Next", Avenir, Roboto, "Helvetica Neue",
             Arial, sans-serif;
  --bs-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "JetBrains Mono",
             "Cascadia Mono", Consolas, "Liberation Mono", monospace;

  /* Wordmark face. Falls back to --bs-font until a webfont is installed —
     see the @font-face block below. */
  --bs-display: "IBM Plex Sans", var(--bs-font);

  /* Rhythm */
  /* Wide container — used by the home page, whose card grids need the room.
     clamp(floor, preferred, ceiling): never narrower than the 1400px the
     design was approved at, grows with the viewport above that, stops at
     1800px so a very wide monitor does not stretch lines to nonsense.
     A fixed cap turned every pixel above 1400 into margin — 260px a side on a
     1920 screen, 580px on a 2560 one. */
  --bs-container: clamp(1400px, 88vw, 1800px);

  /* Content pages: wide enough to sit comfortably under the full-width banner,
     with text running margin to margin. Paired with the 18px base size below,
     which keeps the character count per line in a workable range. */
  /* Content width on single-column inner pages (Services, Training, About,
     Certification, Lectures, Research, Blog).

     Home uses --bs-container (1400px) directly and is NOT affected by this.
     Course pages also stay at 1400px, by the override near the end of this
     file — they are two-column and need the room.

     History, so nobody "fixes" this back: it was 72rem, which looks like
     1296px at the site's 18px type but is actually 1152px, because `rem`
     resolves against <html> (the browser default 16px) and the 18px is set on
     <body>. That left inner pages 248px narrower than home, which read as a
     mistake. 1200px is a deliberate 200px inset instead — 1280px was tried
     and judged too close to home to read as intentional. Pixels on purpose —
     do not go back to rem here.

     FINAL: inner pages now match the home page exactly. The 200px inset was
     chosen from 1440px screenshots; seen on the real (wider) monitor it read
     as narrow, so the inset was dropped. Referencing --bs-container rather
     than repeating its value means the two can no longer drift apart. */
  --bs-prose-width: var(--bs-container);

  /* Text now fills its column, so per-element measure caps are switched off.
     Set this back to a ch value to re-introduce a narrower text column. */
  /* "Measure" is the typographic term for line length. Text fills its column.
     DO NOT set this to a ch value without checking the HOME page: it is not
     only used by inner-page prose. .bs-section-lead, .bs-prose p,
     .bs-cta-close and .bs-entry-text all read it, and those are home-page
     components — narrowing it wrecks the home layout. Constraining inner-page
     prose needs a separate token scoped to those pages, not this one. */
  --bs-measure: 100%;
  --bs-radius: 4px;
}

/* --------------------------------------------------------------------------
   Webfonts — SELF-HOSTED, not loaded from a CDN.

   A security company should not send every visitor's IP address to a third
   party just to render text, so these files live on your own server. Download
   the .woff2 files, drop them in static/fonts/, and uncomment the block.
   Nothing else needs to change: the whole site already reads --bs-font,
   --bs-mono and --bs-display.

   Installed: IBM Plex Sans 1.1.0 and IBM Plex Mono 2.5.0, both SIL Open Font
   License (free for commercial use, including merchandise and printed guides).
   Source: https://github.com/IBM/plex/releases

   Only the five weights actually used are shipped — 286 KB total. Adding more
   weights means more download for every visitor, so add one only when a design
   actually calls for it.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   THE TYPE SCALE KNOB.

   Everything in this stylesheet that is sized in `rem` — every heading,
   kicker, label, and most spacing — resolves against THIS value, not against
   the body size. So this is the one place to make the whole page larger or
   smaller, and it behaves exactly like browser zoom: type and spacing grow
   together, proportionally.

   CURRENTLY NEUTRAL (100% = the browser's own 16px). 110% and 120% were both
   tried and judged too large; the site was reverted to its original scale on
   27 Aug 2026 to work forward from a known-good baseline.

   This rule is kept, set to 100%, because it is the correct place to adjust
   page scale if we ever do. Raising `body` alone is NOT the correct place —
   that grows paragraphs and leaves every rem-based heading and gap where it
   was, which is what made the page read as disproportionate.

   Do NOT try to make the page bigger by raising the body font-size alone.
   That grows paragraphs while leaving every heading and gap where it was,
   which is why the page previously read as disproportionate rather than
   simply larger.
   --------------------------------------------------------------------------- */
html {
  font-size: 100%;
  background: var(--bs-bg);
  -webkit-text-size-adjust: 100%;
}

/* .bs-body is on the <body> tag purely to win specificity over any leftover
   Tachyons typography class. */
body,
body.bs-body {
  background: var(--bs-bg) !important;
  color: var(--bs-text);
  font-family: var(--bs-font);
  /* 18px — the original size, restored 27 Aug 2026 after 19, 20 and 24 were
     each tried and judged too large. To resize the whole page, change the
     root above, not this. */
  font-size: 18px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main {
  background: var(--bs-bg);
}

::selection {
  background: var(--bs-accent);
  color: #04121A;
}

/* Ananke applies text-align:center on large screens and the old stylesheet
   forced justification. Long technical prose reads better ragged-right. */
.cf,
.nested-links,
article,
article section {
  text-align: left;
}

article {
  opacity: 1;
  width: 100%;
  height: auto;
}

/* --------------------------------------------------------------------------
   Content typography
   -------------------------------------------------------------------------- */

/* Wide container, readable text column.
   Structural elements (section rules, tables, grids) span the full width;
   running prose stays at a readable measure so long course and service pages
   don't turn into 200-character lines. */
main article,
main article > section,
main article > .bs-prose {
  color: var(--bs-text-soft);
  max-width: var(--bs-prose-width);
  margin-inline: auto;
}

/* ALL horizontal padding is set here, on the <article> only.
   [class] is mandatory: the theme puts .ph5-l (4rem) directly on the article
   on the Training page, and on a nested <section> everywhere else. A plain
   descendant selector scores lower than a class and loses silently, which is
   what made Training sit 4rem in and other pages 6rem in while the home page
   sat at 2rem. */
main article[class],
main article {
  max-width: var(--bs-prose-width);
  padding-left: 2rem;
  padding-right: 2rem;
  padding-top: clamp(1.5rem, 2.8vw, 2.25rem);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* Inner wrappers add nothing horizontally — otherwise the padding compounds. */
main article > section[class],
main article > section,
main article > .bs-prose {
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  padding-bottom: 0;
  max-width: none;
}

/* The first element carries its own top margin on top of the padding above,
   which doubled the gap under the banner. Remove it so the padding alone
   controls the spacing. */
main article > *:first-child,
main article > section > *:first-child,
main article > .bs-prose > *:first-child {
  margin-top: 0;
}

/* THE ANANKE SPECIFICITY TRAP, AGAIN — the sixth instance. See CLAUDE.md.

   The theme puts Tachyons `.f5` (font-size: 1rem) on the <article> of the
   Training page and on an inner <section> everywhere else. A class beats the
   `body` element selector, so those pages were pinned to 1rem no matter what
   base size was set: measured at 16px on About, Training, Services,
   Certification and Lectures while the home page and course pages — which use
   our own templates and carry no Tachyons classes — correctly showed 20px.

   `inherit` rather than a fixed size, so these follow the body and stay in
   step if the scale ever changes again. */
main article.f5,
main article .f5 {
  font-size: inherit;
}

main article p,
main article li,
main article blockquote,
main article h4 {
  color: var(--bs-text-soft);
  max-width: var(--bs-measure);
  /* Also inherit: the theme sizes some list items at 0.8em, which measured
     12.8px on About. */
  font-size: inherit;
}

main article table,
main article .bs-grid,
main article .bs-chips,
main article .bs-stats,
main article .bs-cta {
  max-width: none;
}

@media screen and (max-width: 60em) {
  main article[class],
  main article {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

/* Opening paragraph treatment: larger and brighter than body copy, so every
   page starts with a clear statement rather than dropping straight into
   running text.
   Three selectors because the theme wraps content differently per template —
   Training puts <p> directly in <article>, most pages nest it in <section>,
   and our own templates use .bs-prose. Without all three, only some pages got
   the treatment. */
main article > p:first-of-type,
main article > section > p:first-of-type,
main article > .bs-prose > p:first-of-type {
  /* `em`, NOT `rem`. This must be 15% larger than the BODY text, and `rem`
     measures against <html> (16px) while the body runs at 18px — so 1.15rem
     gave 18.4px against 18px body, a 2% difference nobody can see. `em`
     measures against the parent, so it tracks the body size as intended:
     18 x 1.15 = 20.7px.
     Same unit trap that made --bs-prose-width 1152px when 72rem was meant to
     read as 1296px. Any size meant to relate to body text belongs in `em`. */
  font-size: 1.15em;
  line-height: 1.65;
  color: var(--bs-text);
}

main article h2,
main article h3,
main article h4 {
  font-family: var(--bs-font);
  color: var(--bs-text);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

main article h2 {
  font-size: 1.9rem;
  margin-top: 3.5rem;
  margin-bottom: 1rem;
}

/* Section headings carry the accent rule — this is what gives long course and
   service pages visible structure instead of an undifferentiated column. */
main article h3 {
  position: relative;
  font-size: 1.4rem;
  margin-top: 3rem;
  margin-bottom: 1rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--bs-border);
}

main article h3::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 56px;
  height: 2px;
  background: var(--bs-accent);
}

main article h4 {
  font-size: 1.1rem;
  margin-top: 2rem;
  margin-bottom: 0.5rem;
  color: var(--bs-text);
}

main article strong {
  color: var(--bs-text);
  font-weight: 600;
}

main article em {
  color: var(--bs-text);
}

main article hr {
  border: 0;
  border-top: 1px solid var(--bs-border);
  margin: 3rem 0;
}

main article blockquote {
  margin: 2rem 0;
  padding: 0.25rem 0 0.25rem 1.25rem;
  border-left: 2px solid var(--bs-accent);
  color: var(--bs-text);
  font-style: normal;
}

/* Lists: accent markers instead of default discs */
main article ul {
  list-style: none;
  padding-left: 0;
}

main article ul > li {
  position: relative;
  padding-left: 1.6rem;
  margin-bottom: 0.55rem;
}

main article ul > li::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 0.72em;
  width: 6px;
  height: 6px;
  background: var(--bs-accent);
  transform: rotate(45deg);
}

main article ol {
  padding-left: 1.3rem;
}

main article ol > li {
  margin-bottom: 0.55rem;
}

main article ol > li::marker {
  color: var(--bs-accent);
  font-family: var(--bs-mono);
  font-size: 0.9em;
}

/* Links */
main article a,
.bs-link {
  color: var(--bs-accent);
  text-decoration: none;
  border-bottom: 1px solid var(--bs-accent-dim);
  transition: color 0.15s ease, border-color 0.15s ease;
}

main article a:hover,
.bs-link:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
  text-decoration: none;
}

main article img {
  max-width: 100%;
  height: auto;
  border-radius: var(--bs-radius);
}

main article a:has(img) {
  border-bottom: 0;
}

code,
kbd,
samp {
  font-family: var(--bs-mono);
  font-size: 0.9em;
  background: var(--bs-surface);
  border: 1px solid var(--bs-border);
  border-radius: 3px;
  padding: 0.1em 0.4em;
  color: var(--bs-accent-hi);
}

pre {
  background: var(--bs-surface);
  border: 1px solid var(--bs-border);
  border-radius: var(--bs-radius);
  padding: 1rem 1.25rem;
  overflow-x: auto;
}

pre code {
  background: none;
  border: 0;
  padding: 0;
  color: var(--bs-text-soft);
}

/* --------------------------------------------------------------------------
   Header / navigation
   -------------------------------------------------------------------------- */

/* The hero treatment is the part people already liked — deepen the dimming so
   the storm image keeps its drama while the text gains contrast. */
header.cover > .bg-black-60 {
  background: linear-gradient(
    180deg,
    rgba(6, 10, 14, 0.72) 0%,
    rgba(6, 10, 14, 0.80) 55%,
    rgba(11, 15, 20, 0.96) 100%
  );
}

header.cover {
  background-size: cover;
  background-position: center;
  border-bottom: 1px solid var(--bs-border);
}

header nav {
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

/* --------------------------------------------------------------------------
   Brand lockup (mark + wordmark)
   -------------------------------------------------------------------------- */

.bs-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--bs-text);
}

/* With no company name in the banner, the logo is the only place the identity
   is stated — so it carries more weight than a typical nav logo. */
.bs-brand-mark {
  width: 48px;
  height: 48px;
  flex: none;
  display: block;
}

.bs-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

/* "Blackstorm" is the name — it carries the weight.
   "Security" is the category descriptor — subordinate, but still readable
   when small, which is why the tracking is 0.2em and not wider. */
.bs-brand-name {
  font-family: var(--bs-display);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: var(--bs-text);
}

/* Registered mark: small and raised, never competing with the wordmark */
/* The ® now sits on SECURITY, which is the smaller of the two lines, so it is
   sized against that rather than against BLACKSTORM: 0.55em keeps it legible
   where 0.36em would have vanished. `letter-spacing: normal` cancels the 0.2em
   tracking on .bs-brand-sub, which would otherwise push it a full unit away
   from the Y. */
.bs-brand-r {
  font-size: 0.55em;
  font-weight: 600;
  letter-spacing: normal;
  vertical-align: top;
  line-height: 1;
  margin-left: 0.12em;
  top: -0.1em;
  position: relative;
}

.bs-brand-sub {
  font-family: var(--bs-mono);
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--bs-text-soft);
  margin-top: 0.38rem;
}

/* Company motto under the wordmark. Deliberately quiet — it should read as
   part of the identity block, the way a tagline sits on a letterhead, and not
   compete with the page subtitle in the banner below it. */
.bs-brand-motto {
  font-family: var(--bs-mono);
  font-size: 0.62rem;
  font-weight: 400;
  letter-spacing: 0.055em;
  color: var(--bs-muted);
  margin-top: 0.42rem;
  white-space: nowrap;
}

.bs-brand:hover .bs-brand-name {
  color: var(--bs-accent-hi);
}

.bs-brand:hover .bs-brand-sub,
.bs-brand:hover .bs-brand-motto {
  color: var(--bs-text-soft);
}

/* Below 60em the nav stacks and there is no room for a 41-character line
   beside the menu, so the footer carries the motto alone. */
@media screen and (max-width: 60em) {
  .bs-brand-motto { display: none; }
}

@media screen and (max-width: 30em) {
  .bs-brand-mark { width: 32px; height: 32px; }
  .bs-brand-name { font-size: 1rem; }
}

header nav a.white-90,
header nav a.hover-white {
  color: var(--bs-text) !important;
  letter-spacing: 0.02em;
}

header nav ul li a {
  position: relative;
  font-size: 0.95rem !important;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding-bottom: 4px;
  transition: color 0.15s ease;
}

header nav ul li a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 2px;
  background: var(--bs-accent);
  transition: width 0.2s ease;
}

header nav ul li a:hover {
  color: var(--bs-accent-hi) !important;
}

header nav ul li a:hover::after {
  width: 100%;
}

/* Hero (the banner block with the storm photograph).
   The title is a PAGE title — "Training", "Research", and the company name only
   on the home page — so it is set in the same family as the logo but at a
   different weight and case. Related, deliberately not identical. */
/* Large mark above the hero title. Switched on with `hero_mark: true` in a
   page's front matter. Use it on the home page only: on inner pages the hero
   title is a page name ("Training"), and a mark beside it reads as a false
   sub-brand lockup rather than as the company logo. */
.bs-hero-mark {
  display: block;
  width: clamp(56px, 8vw, 92px);
  height: auto;
  margin: 0 0 1.4rem;
}

@media screen and (min-width: 60em) {
  .bs-hero-mark { margin-inline: auto; }
}

/* Horizontal variant: mark beside the title, same arrangement as the nav. */
.bs-hero-lockup {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2vw, 1.6rem);
}

@media screen and (min-width: 60em) {
  .bs-hero-lockup { justify-content: center; }
}

.bs-hero-mark-inline {
  margin: 0;
  flex: none;
  width: clamp(48px, 7vw, 86px);
}

.bs-hero-title {
  font-family: var(--bs-display);
  color: var(--bs-text);
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.6);
}

/* The company name on the home page carries a little more presence */
.home .bs-hero-title {
  font-size: clamp(2.25rem, 5vw, 3.75rem);
}

/* The banner background image.
   ---------------------------------------------------------------------------
   This lives here rather than in a style attribute on <header>, so that the
   Content Security Policy can forbid inline styles entirely
   (`style-src 'self'`, no 'unsafe-inline'). Every page uses the same image, so
   there is nothing per-page to express.

   TO CHANGE THE BANNER IMAGE, change the url() below. Setting `featured_image`
   in front matter no longer has any visual effect — it is still read by the
   templates to decide *whether* a banner is shown, but not which image. */
.bs-cover {
  background-image: url("/images/storm1.jpg");
}

/* The banner's content block. Generous, scaling breathing room above and
   below the title so it never sits against the navigation or the fold. */
/* Banner height is set here. Inner pages are the tighter default because their
   title is smaller ("Training", "Research"); the home page gets a little more
   room below, since its title is larger. Raise or lower the last value in each
   clamp to adjust on a desktop screen. */
.bs-hero-body {
  padding-top: clamp(1.15rem, 2vw, 1.65rem);
  padding-bottom: clamp(1.25rem, 2.2vw, 1.8rem);
  padding-left: 1.5rem;
  padding-right: 1.5rem;
  text-align: left;
}

.home .bs-hero-body {
  padding-top: clamp(1.6rem, 3vw, 2.5rem);
  padding-bottom: clamp(1.5rem, 2.6vw, 2.1rem);
}

@media screen and (min-width: 60em) {
  .bs-hero-body {
    text-align: center;
    padding-left: 2rem;
    padding-right: 2rem;
  }
}

/* Page subtitle — e.g. "Providing Skills for Hackers" on Training */
.bs-hero-sub,
header .fw1 {
  color: var(--bs-text-soft);
  font-family: var(--bs-mono);
  font-size: 0.95rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  max-width: 42ch;
  /* margin-block:0 removes the browser's default h2 margin, which was adding
     roughly 0.8rem of dead space under the subtitle on top of the band's
     own padding. The gap above comes from the ::before rule instead. */
  margin: 0 auto;
}

.bs-hero-sub::before,
header h2::before {
  content: "";
  display: block;
  width: 40px;
  height: 2px;
  background: var(--bs-accent);
  margin: 1.25rem auto 1.25rem;
}

/* --------------------------------------------------------------------------
   Home page components
   -------------------------------------------------------------------------- */

.bs-section {
  max-width: var(--bs-container);
  margin-inline: auto;
  padding: 4.5rem 2rem;
}

.bs-section + .bs-section {
  border-top: 1px solid var(--bs-border);
}

.bs-kicker {
  font-family: var(--bs-mono);
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--bs-accent);
  margin-bottom: 0.9rem;
}

.bs-section-title {
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--bs-text);
  margin: 0 0 0.75rem;
  line-height: 1.2;
}

.bs-section-lead {
  color: var(--bs-muted);
  max-width: var(--bs-measure);
  margin: 0 0 2.5rem;
}

/* Opening statement carries more weight than a normal section title */
.bs-intro-title {
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  max-width: 20ch;
}

.bs-intro-lead {
  font-size: 1.1rem;
  color: var(--bs-text-soft);
}

/* Markdown body rendered inside home sections gets the same treatment as
   article prose (which is scoped to `main article`). */
.bs-prose p,
.bs-prose li {
  color: var(--bs-text-soft);
  max-width: var(--bs-measure);
}

.bs-prose a {
  color: var(--bs-accent);
  text-decoration: none;
  border-bottom: 1px solid var(--bs-accent-dim);
}

.bs-prose a:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
}

.bs-prose img {
  max-width: 100%;
  height: auto;
  border-radius: var(--bs-radius);
}

.bs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.25rem;
}

.bs-card {
  display: block;
  position: relative;
  background: var(--bs-surface);
  border: 1px solid var(--bs-border);
  border-radius: var(--bs-radius);
  padding: 1.6rem 1.5rem;
  text-decoration: none;
  overflow: hidden;
  transition: border-color 0.18s ease, background 0.18s ease,
              transform 0.18s ease;
}

.bs-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--bs-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.22s ease;
}

a.bs-card:hover {
  background: var(--bs-surface-hi);
  border-color: var(--bs-border-hi);
  transform: translateY(-2px);
}

a.bs-card:hover::before {
  transform: scaleX(1);
}

.bs-card-title {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--bs-text);
  margin: 0 0 0.5rem;
  line-height: 1.3;
}

.bs-card-text {
  color: var(--bs-muted);
  font-size: 0.95rem;
  line-height: 1.6;
  margin: 0;
}

.bs-card-meta {
  display: block;
  font-family: var(--bs-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--bs-accent);
  margin-bottom: 0.7rem;
}

/* Platform / capability chips */
.bs-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.bs-chip {
  font-family: var(--bs-mono);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--bs-text-soft);
  background: var(--bs-surface);
  border: 1px solid var(--bs-border);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
}

/* Credibility strip */
.bs-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1.25rem;
}

.bs-stat-value {
  font-family: var(--bs-mono);
  font-size: 2rem;
  font-weight: 600;
  color: var(--bs-accent);
  line-height: 1.1;
}

.bs-stat-label {
  font-size: 0.85rem;
  color: var(--bs-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-top: 0.4rem;
}

/* Buttons */
.bs-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 2rem;
}

.bs-btn {
  display: inline-block;
  font-family: var(--bs-mono);
  font-size: 0.85rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 0.85rem 1.6rem;
  border-radius: var(--bs-radius);
  text-decoration: none;
  border: 1px solid var(--bs-accent);
  transition: background 0.16s ease, color 0.16s ease, box-shadow 0.16s ease;
}

.bs-btn-primary {
  background: var(--bs-accent);
  color: #04121A;
}

.bs-btn-primary:hover {
  background: var(--bs-accent-hi);
  border-color: var(--bs-accent-hi);
  box-shadow: 0 0 0 4px var(--bs-accent-glow);
}

.bs-btn-ghost {
  background: transparent;
  color: var(--bs-accent);
}

.bs-btn-ghost:hover {
  background: var(--bs-accent-glow);
  color: var(--bs-accent-hi);
}

/* Inline CTA band (also usable from markdown pages) */
.bs-cta {
  background: var(--bs-bg-alt);
  border: 1px solid var(--bs-border);
  border-left: 2px solid var(--bs-accent);
  border-radius: var(--bs-radius);
  padding: 2.75rem 2.5rem;
  margin: 3rem 0 0;
}

.bs-cta-title {
  font-size: clamp(1.7rem, 3.2vw, 2.5rem);
  max-width: 22ch;
}

.bs-cta-lead {
  font-size: 1.05rem;
  color: var(--bs-text-soft);
  margin-bottom: 2rem;
}

/* Service lines inside the closing call to action */
.bs-cta-points {
  list-style: none;
  padding: 0;
  margin: 0 0 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1rem 2.5rem;
}

.bs-cta-points li {
  position: relative;
  padding-left: 1.6rem;
  color: var(--bs-muted);
  font-size: 0.95rem;
  line-height: 1.6;
  max-width: 52ch;
}

.bs-cta-points li::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 0.68em;
  width: 6px;
  height: 6px;
  background: var(--bs-accent);
  transform: rotate(45deg);
}

.bs-cta-points strong {
  color: var(--bs-text);
  font-weight: 600;
}

.bs-cta-points a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease;
}

.bs-cta-points a:hover strong {
  color: var(--bs-accent-hi);
}

.bs-cta-points a:hover {
  border-bottom-color: var(--bs-accent-hi);
}

.bs-cta-close {
  color: var(--bs-text-soft);
  max-width: var(--bs-measure);
  margin: 0;
}

/* --------------------------------------------------------------------------
   Schedule table (Training)
   -------------------------------------------------------------------------- */

table {
  border-collapse: collapse;
  font-family: var(--bs-font);
  width: 100%;
  margin: 2rem 0;
  background: var(--bs-bg-alt);
  border: 1px solid var(--bs-border);
  border-radius: var(--bs-radius);
  overflow: hidden;
}

table td {
  padding: 0.85rem 1rem;
}

/* Track headers (the single full-width cells) */
table thead td[colspan] {
  background: var(--bs-surface-hi);
  color: var(--bs-accent);
  font-family: var(--bs-mono);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  text-align: left;
  border: 0;
  border-top: 1px solid var(--bs-border);
  padding: 1.1rem 1rem;
}

/* Column headers */
table thead td {
  background: var(--bs-surface);
  color: var(--bs-muted);
  font-weight: 600;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border: 0;
  border-bottom: 1px solid var(--bs-border);
  text-align: left;
}

table tbody td {
  color: var(--bs-text-soft);
  border: 0;
  border-bottom: 1px solid var(--bs-border);
  font-size: 0.95rem;
  text-align: left;
}

table tbody tr,
table tbody tr:nth-child(odd) {
  background: transparent;
  text-align: left;
  font-size: 0.95rem;
  transition: background 0.14s ease;
}

table tbody tr:hover {
  background: var(--bs-surface);
}

/* Date and hours columns read as data */
table tbody td:nth-child(2),
table tbody td:nth-child(3) {
  font-family: var(--bs-mono);
  font-size: 0.85rem;
  color: var(--bs-muted);
  white-space: nowrap;
}

table a,
main article table a {
  color: var(--bs-text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  font-weight: 500;
}

table a:hover,
main article table a:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
  text-decoration: none;
}

.schedule tr {
  line-height: 1.5;
}

/* Small screens: let the wide schedule scroll instead of breaking layout */
@media screen and (max-width: 40em) {
  table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

/* The partial no longer emits Tachyons classes, so these plain .bs-* selectors
   win on their own — no [class] hack and no !important needed. */

.bs-foot {
  background: var(--bs-bg-alt);
  border-top: 1px solid var(--bs-border);
  padding: 1.75rem 1.5rem 1.15rem;
}

/* Lockup and motto sit on one line, so the whole footer is two shallow rows. */
.bs-foot-inner {
  max-width: var(--bs-container);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2.5rem;
}

.bs-foot-lockup {
  display: inline-flex;
}

/* The motto is the company line, so it takes the accent rule — the one place
   in the footer where the cyan is spent. */
.bs-foot-motto {
  font-family: var(--bs-mono);
  font-size: 0.82rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--bs-text-soft);
  margin: 0;
  padding-left: 0.9rem;
  border-left: 2px solid var(--bs-accent);
}

.bs-foot a {
  color: var(--bs-text-soft);
  text-decoration: none;
  transition: color 0.15s ease;
}

.bs-foot a:hover,
.bs-foot a:focus-visible {
  color: var(--bs-accent-hi);
  text-decoration: none;
}

.bs-foot-lockup:hover .bs-brand-name {
  color: var(--bs-accent-hi);
}

.bs-foot-bar {
  max-width: var(--bs-container);
  margin: 1.5rem auto 0;
  padding-top: 0.95rem;
  border-top: 1px solid var(--bs-border);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  font-family: var(--bs-mono);
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--bs-muted);
}

@media screen and (max-width: 30em) {
  .bs-foot-bar {
    justify-content: flex-start;
  }
}

/* --------------------------------------------------------------------------
   Publications (Exploit Reversing articles) & Blog
   -------------------------------------------------------------------------- */

.bs-series {
  margin-top: 3.5rem;
}

.bs-series-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--bs-border);
  margin-bottom: 1.75rem;
}

.bs-series-title {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--bs-text);
  margin: 0;
  letter-spacing: -0.01em;
}

.bs-series-note {
  font-family: var(--bs-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-muted);
}

.bs-series-lead {
  color: var(--bs-muted);
  max-width: var(--bs-measure);
  margin: -1rem 0 1.75rem;
}

/* One entry per article */
.bs-entry {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 0 1.5rem;
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--bs-border);
  align-items: start;
}

/* Offset so an anchored article isn't hidden under the top of the viewport */
.bs-entry[id] {
  scroll-margin-top: 2rem;
}

.bs-entry:target .bs-entry-id {
  background: var(--bs-accent);
  color: #04121A;
  border-color: var(--bs-accent);
}

.bs-entry:hover .bs-entry-id {
  color: var(--bs-accent-hi);
  border-color: var(--bs-accent-hi);
}

.bs-entry-id {
  font-family: var(--bs-mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--bs-accent);
  border: 1px solid var(--bs-accent-dim);
  border-radius: var(--bs-radius);
  padding: 0.3rem 0.1rem;
  text-align: center;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.bs-entry-title {
  font-size: 1.06rem;
  font-weight: 600;
  line-height: 1.4;
  margin: 0 0 0.3rem;
}

.bs-entry-title a {
  color: var(--bs-text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.bs-entry-title a:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
}

.bs-entry-text {
  color: var(--bs-muted);
  font-size: 0.95rem;
  line-height: 1.6;
  margin: 0 0 0.45rem;
  max-width: var(--bs-measure);
}

.bs-entry-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  font-family: var(--bs-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--bs-muted);
}

.bs-entry-meta a {
  color: var(--bs-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.bs-entry-meta a:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
}

/* Expandable table of contents per article */
.bs-topics {
  margin: 0.85rem 0 0.25rem;
}

.bs-topics > summary {
  cursor: pointer;
  display: inline-block;
  font-family: var(--bs-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-muted);
  list-style: none;
  transition: color 0.15s ease;
}

.bs-topics > summary::-webkit-details-marker {
  display: none;
}

.bs-topics > summary::before {
  content: "+ ";
  color: var(--bs-accent);
  font-weight: 600;
}

.bs-topics[open] > summary::before {
  content: "− ";
}

.bs-topics > summary:hover {
  color: var(--bs-accent-hi);
}

.bs-topics .bs-chips {
  margin-top: 0.85rem;
}

.bs-topics .bs-chip {
  font-size: 0.76rem;
  padding: 0.3rem 0.75rem;
  background: var(--bs-bg-alt);
}

.bs-entry-tools {
  font-size: 0.83rem;
  color: var(--bs-muted);
  margin: 0.75rem 0 0;
  max-width: var(--bs-measure);
}

.bs-entry-tools span {
  font-family: var(--bs-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-accent);
  margin-right: 0.5rem;
}

/* Stat strip used inline at the top of a content page */
.bs-stats-inline {
  padding: 1.5rem 0 0.5rem;
  border-top: 1px solid var(--bs-border);
  border-bottom: 1px solid var(--bs-border);
  margin-bottom: 1rem;
}

/* Certification milestones on a track page */
.bs-milestones {
  list-style: none;
  padding: 0;
  margin: 0;
}

.bs-milestones li {
  padding: 0.75rem 0 0.75rem 1.6rem;
  position: relative;
  border-bottom: 1px solid var(--bs-border);
  color: var(--bs-text-soft);
  max-width: var(--bs-measure);
}

.bs-milestones li::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 1.35em;
  width: 6px;
  height: 6px;
  background: var(--bs-accent);
  transform: rotate(45deg);
}

.bs-milestones strong {
  color: var(--bs-text);
}

/* Marks an entry whose details still need to be filled in */
.bs-entry-todo .bs-entry-id {
  color: var(--bs-muted);
  border-color: var(--bs-border);
}

@media screen and (max-width: 40em) {
  .bs-entry {
    grid-template-columns: 1fr;
    gap: 0.6rem;
  }
  .bs-entry-id {
    justify-self: start;
    padding-inline: 0.75rem;
  }
}

/* Blog post list */
.bs-post {
  display: block;
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--bs-border);
  text-decoration: none;
}

.bs-post:hover .bs-post-title {
  color: var(--bs-accent-hi);
}

.bs-post-date {
  font-family: var(--bs-mono);
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-accent);
}

.bs-post-title {
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--bs-text);
  margin: 0.4rem 0 0.5rem;
  line-height: 1.3;
  transition: color 0.15s ease;
}

.bs-post-summary {
  color: var(--bs-muted);
  font-size: 0.97rem;
  margin: 0;
  max-width: var(--bs-measure);
}

.bs-empty {
  color: var(--bs-muted);
  font-style: italic;
  padding: 2rem 0;
}

/* Post meta on a single post */
.bs-post-meta {
  font-family: var(--bs-mono);
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-muted);
  padding-bottom: 1.25rem;
  margin-bottom: 2rem;
  border-bottom: 1px solid var(--bs-border);
}

/* --------------------------------------------------------------------------
   Components usable from markdown (see layouts/shortcodes)
   -------------------------------------------------------------------------- */

.bs-grid-content {
  margin: 1.75rem 0 2.5rem;
}

/* Static (non-link) card */
.bs-card-static {
  position: relative;
}

div.bs-card-static:hover {
  border-color: var(--bs-border-hi);
}

.bs-card-badge {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  font-family: var(--bs-mono);
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-accent);
  border: 1px solid var(--bs-accent-dim);
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
}

.bs-card-title { padding-right: 5.5rem; }
.bs-card-static .bs-card-title:only-child,
.bs-card-static .bs-card-title { margin-bottom: 0.6rem; }

.bs-card-body p,
.bs-card-body li {
  color: var(--bs-muted);
  font-size: 0.94rem;
  line-height: 1.6;
  max-width: none;
}

.bs-card-body p:last-child { margin-bottom: 0; }

.bs-card-body ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.bs-card-body ul > li {
  position: relative;
  padding-left: 1.05rem;
  margin-bottom: 0.3rem;
}

.bs-card-body ul > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.65em;
  width: 5px;
  height: 5px;
  background: var(--bs-accent);
  transform: rotate(45deg);
}

/* Ordered sequence */
.bs-steps {
  list-style: none;
  counter-reset: bs-step;
  padding: 0;
  margin: 1.75rem 0 2.5rem;
}

.bs-step {
  counter-increment: bs-step;
  position: relative;
  padding-left: 3.6rem;
  padding-bottom: 1.6rem;
  margin-bottom: 1.6rem;
  border-bottom: 1px solid var(--bs-border);
}

.bs-step:last-child {
  border-bottom: 0;
  padding-bottom: 0;
  margin-bottom: 0;
}

.bs-step::before {
  content: counter(bs-step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0;
  width: 2.5rem;
  text-align: center;
  font-family: var(--bs-mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--bs-accent);
  border: 1px solid var(--bs-accent-dim);
  border-radius: var(--bs-radius);
  padding: 0.3rem 0;
}

.bs-step-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--bs-text);
  margin: 0 0 0.4rem;
  border: 0;
  padding: 0;
}

.bs-step-title::before { display: none; }

.bs-step-body p {
  margin: 0 0 0.6rem;
  max-width: none;
}

.bs-step-body p:last-child { margin-bottom: 0; }

.bs-chips-content {
  margin: 1.5rem 0 2rem;
}

/* --------------------------------------------------------------------------
   Course pages — description beside a facts panel
   -------------------------------------------------------------------------- */

.bs-course {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20rem;
  gap: 3rem;
  align-items: start;
}

@media screen and (max-width: 64em) {
  .bs-course {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  /* Facts first on a phone: they answer the practical questions fastest */
  .bs-course-facts { order: -1; }
}

.bs-facts-card {
  background: var(--bs-bg-alt);
  border: 1px solid var(--bs-border);
  border-left: 2px solid var(--bs-accent);
  border-radius: var(--bs-radius);
  padding: 1.5rem 1.4rem;
  position: sticky;
  top: 1.5rem;
}

.bs-facts-title {
  font-family: var(--bs-mono);
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--bs-accent);
  margin: 0 0 1.1rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--bs-border);
}

.bs-facts {
  margin: 0;
}

.bs-facts dt {
  font-family: var(--bs-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--bs-muted);
  margin-top: 1rem;
}

.bs-facts dt:first-of-type { margin-top: 0; }

.bs-facts dd {
  margin: 0.3rem 0 0;
  color: var(--bs-text);
  font-size: 0.95rem;
  line-height: 1.5;
}

.bs-facts dd a {
  color: var(--bs-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.bs-facts dd a:hover {
  color: var(--bs-accent-hi);
  border-bottom-color: var(--bs-accent-hi);
}

.bs-facts-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.bs-facts-list li {
  position: relative;
  padding-left: 0.9rem;
  margin-bottom: 0.25rem;
  color: var(--bs-text-soft);
  font-size: 0.92rem;
}

.bs-facts-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 4px;
  height: 4px;
  background: var(--bs-accent);
  transform: rotate(45deg);
}

.bs-facts-actions {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1.6rem;
  padding-top: 1.3rem;
  border-top: 1px solid var(--bs-border);
}

.bs-facts-actions .bs-btn {
  text-align: center;
  padding-inline: 1rem;
  font-size: 0.78rem;
}

/* Course pages get the wide container, since they now have two columns */
body.bs-course-page main article[class],
body.bs-course-page main article {
  max-width: var(--bs-container);
}

/* --------------------------------------------------------------------------
   Accessibility
   -------------------------------------------------------------------------- */

a:focus-visible,
.bs-btn:focus-visible,
.bs-card:focus-visible {
  outline: 2px solid var(--bs-accent);
  outline-offset: 3px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}
