* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, sans-serif;
  color: #1f2328;
  background: #f6f7f9;
  line-height: 1.55;
}

a { color: #b45309; }
a:hover { color: #f6821f; }

/* Two rows on purpose, at every width: the launcher and the brand on the first,
   the nav on its own second one. The previous single-row bar had to be tuned
   against seven links wrapping - which produced the states this replaces: the
   launcher stranded on a line of its own, then the nav dropping flush against
   the top of the page. A nav that always owns a full row cannot wrap into
   anything. */
.topbar {
  background: #14171f;
  color: white;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  column-gap: 16px;
  row-gap: 8px;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar .brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-weight: 700;
  color: white;
  text-decoration: none;
  white-space: nowrap;
}
.topbar .brand span { font-weight: 400; color: #9aa4b2; font-size: 0.85rem; }
/* flex-basis forces the second row; the DOM puts the menu button ahead of it
   so the button stays up on the first. Right-aligned, so the links sit under
   the page's own right margin rather than trailing off from the brand. */
.topbar nav {
  display: flex; gap: 2px; flex-wrap: wrap;
  flex-basis: 100%;
  justify-content: flex-end;
}
.topbar nav a {
  color: #cbd5e1;
  text-decoration: none;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: 0.76rem;
}
.topbar nav a:hover { background: #2a2f3a; color: white; }
.topbar nav a.active { background: #f6821f; color: white; }

/* ----------------------------------------------------- narrow screens --- */
/* The menu button. Hidden until the bar carries `nav-collapsed` - see below.
   Same 36px box and borders as the launcher, so the two read as a pair, and
   margin-left:auto keeps it on the right of the first row. */
.nav-toggle {
  display: none;
  margin-left: auto;
  align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  background: transparent; color: #cbd5e1;
  border: 1px solid #2a2f3a; border-radius: 6px; cursor: pointer;
}
.nav-toggle svg { width: 20px; height: 20px; }
.nav-toggle:hover,
.nav-toggle[aria-expanded="true"] { background: #2a2f3a; color: white; }

/* The collapse point is MEASURED, not guessed: site.js adds `nav-collapsed` to
   the bar when the links no longer fit on one row, and removes it when they do.
   Three hand-picked breakpoints came before this, each wrong in a different
   way - the last showed the hamburger at 860px when the links only need about
   450px, so a whole band of widths hid a nav that would have fitted.

   With JavaScript off the class is never added, so the links stay visible and
   wrap onto a second row: untidy at the very narrowest widths, and navigable,
   which is the trade a site's primary nav should make. */
.topbar.nav-collapsed { column-gap: 12px; }
.topbar.nav-collapsed .nav-toggle { display: inline-flex; }
.topbar.nav-collapsed nav { display: none; }
.topbar.nav-collapsed nav.open {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 2px;
}
.topbar.nav-collapsed nav.open a { padding: 10px 12px; }

/* The strapline goes when the FIRST row gets tight - the launcher, the brand
   and the menu button. Nothing to do with the nav, which has its own row, so
   this one stays a plain media query. */
@media (max-width: 640px) {
  .topbar .brand span { display: none; }
}

/* ------------------------------------------------------- app launcher --- */
/* The same 3x3 waffle the five apps carry. Tile geometry is copied from
   hr-app/web/src/styles.css (.ww-app-grid and friends) so the panel is the
   same object in every corner of the suite; only the surrounding chrome
   differs, because this topbar is dark and theirs are not.

   First in the bar, before the brand - unlike the apps, which put theirs on
   the right. Here the right-hand slot belongs to the menu button, and two
   similar square buttons side by side were being read as one control. Being
   first also means it is never the item that wraps, since wrapping only pushes
   LATER items onto a new row. */
.launcher { position: relative; display: inline-flex; }
.launcher-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  background: transparent; color: #cbd5e1;
  border: 1px solid #2a2f3a; border-radius: 6px; cursor: pointer;
}
.launcher-btn svg { width: 20px; height: 20px; fill: currentColor; }
.launcher-btn:hover,
.launcher-btn[aria-expanded="true"] { background: #2a2f3a; color: white; }

.launcher-panel {
  /* Anchored left, because the button is the first thing in the bar. It was
     right-anchored when it sat on the far right, which opened the panel
     leftwards off the screen once it moved. */
  position: absolute; top: calc(100% + 8px); left: 0;
  width: 320px; padding: 16px;
  /* So it cannot overhang the other edge on a phone-width window. */
  max-width: calc(100vw - 32px);
  box-sizing: border-box;
  background: white; color: #1f2328;
  border: 1px solid #e5e7eb; border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  z-index: 20;
}
.launcher-panel[hidden] { display: none; }
.launcher-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.launcher-divider { height: 1px; background: #e5e7eb; margin: 12px -16px; }
.launcher-tile {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 12px 6px; border-radius: 6px; text-decoration: none; color: #1f2328;
}
.launcher-tile:hover { background: #f6f7f9; color: #1f2328; }
.launcher-tile.current { background: #fff7ed; }
.launcher-icon {
  width: 40px; height: 40px; border-radius: 6px; color: white;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.8125rem; font-weight: 600;
}
.launcher-label { font-size: 0.8125rem; text-align: center; }
.launcher-note { font-size: 0.6875rem; color: #6b7280; text-align: center; line-height: 1.2; }
/* site.js strips the href when the zone is unknown - a local preview, or any
   hostname that is not demo.<zone> - rather than pretending the link works.
   Without this the tile would look live and do nothing when clicked. */
.launcher-tile:not([href]) { opacity: 0.4; cursor: default; }
.launcher-tile:not([href]):hover { background: none; }

main { max-width: 860px; margin: 0 auto; padding: 32px 24px 72px; }
main.wide { max-width: 1100px; }

h1 { margin: 0 0 8px; font-size: 1.9rem; }
h2 { margin: 32px 0 8px; font-size: 1.3rem; }
h3 { margin: 24px 0 6px; font-size: 1.05rem; }
p { margin: 0 0 12px; }
ul, ol { margin: 0 0 12px; padding-left: 22px; }
li { margin-bottom: 6px; }

.lede { font-size: 1.05rem; color: #4b5563; margin-bottom: 24px; }
.muted { color: #6b7280; }
.crumb { font-size: 0.85rem; color: #6b7280; margin-bottom: 16px; }

.card {
  background: white;
  border-radius: 10px;
  padding: 18px 22px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  margin-bottom: 16px;
}
.card h3 { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; margin-bottom: 16px; }
.grid .card { margin-bottom: 0; }

.callout {
  border-left: 4px solid #f6821f;
  background: #fff7ed;
  padding: 12px 16px;
  border-radius: 0 8px 8px 0;
  margin-bottom: 16px;
}
.callout.warn { border-left-color: #dc2626; background: #fef2f2; }
.callout.ok { border-left-color: #16a34a; background: #f0fdf4; }
.callout > :last-child { margin-bottom: 0; }
/* The callout title, which callout() emits as the first child. Scoped to exactly
   that: as a descendant selector this also made every <strong> in the body a block,
   so an emphasised phrase mid-sentence broke the line before and after itself. */
.callout > strong:first-child { display: block; margin-bottom: 4px; }

pre {
  background: #14171f;
  color: #e5e7eb;
  padding: 14px 16px;
  border-radius: 8px;
  overflow-x: auto;
  font-size: 0.85rem;
  line-height: 1.45;
  margin: 0 0 16px;
}
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }
p code, li code, td code { background: #eef0f2; padding: 1px 5px; border-radius: 4px; }

.prompt {
  position: relative;
  background: white;
  border: 1px solid #fed7aa;
  border-left: 4px solid #f6821f;
  border-radius: 0 8px 8px 0;
  /* Right padding leaves room for the copy button rather than letting a long
     prompt run underneath it. */
  padding: 14px 76px 14px 18px;
  margin-bottom: 16px;
  font-size: 1.02rem;
}
.prompt .label {
  display: block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #b45309;
  margin-bottom: 6px;
}
.prompt q { font-style: italic; }
/* A note to the presenter, outside the quoted prompt so it never reaches the
   clipboard - see prompt() in src/layout.mjs. */
.prompt-aside {
  display: block;
  margin-top: 6px;
  font-size: 0.8125rem;
  font-style: normal;
  color: #6b7280;
}

.tags { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }
.tag {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  background: #eef0f2;
  color: #374151;
  white-space: nowrap;
}
.tag.hr { background: #dbeafe; color: #1d4ed8; }
.tag.crm { background: #dcfce7; color: #15803d; }
.tag.collab { background: #fef9c3; color: #92620a; }
.tag.wiki { background: #ede9fe; color: #6d28d9; }
.tag.intentional { background: #fee2e2; color: #b91c1c; }
.tag.accidental { background: #ffedd5; color: #9a3412; }
.tag.injection { background: #1f2937; color: #f9fafb; }
.tag.cross { background: #e0f2fe; color: #0369a1; }
.tag.finance { background: #d1fae5; color: #065f46; }
.tag.misuse { background: #fce7f3; color: #9d174d; }
.tag.access { background: #e2e8f0; color: #334155; }

table { width: 100%; border-collapse: collapse; background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); margin-bottom: 16px; }
th, td { text-align: left; padding: 9px 14px; border-bottom: 1px solid #eef0f2; vertical-align: top; font-size: 0.92rem; }
th { background: #fafbfc; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: #6b7280; }

.demo-list { list-style: none; padding: 0; }
.demo-list li { margin-bottom: 10px; }
.demo-list a { font-weight: 600; text-decoration: none; }
.demo-list a:hover { text-decoration: underline; }
.demo-list .meta { display: block; color: #6b7280; font-size: 0.9rem; }

footer.site {
  border-top: 1px solid #e5e7eb;
  padding: 20px 24px 40px;
  text-align: center;
  color: #6b7280;
  font-size: 0.85rem;
}

.steps { counter-reset: step; list-style: none; padding-left: 0; }
.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: 34px;
  margin-bottom: 14px;
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 1px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #14171f;
  color: white;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The demo index table: three columns, so a session can be planned by control
   and by value rather than by title alone. */
.demo-table { width: 100%; border-collapse: collapse; margin-bottom: 28px; }
.demo-table th {
  text-align: left; padding: 8px 12px; font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: #6b7280; border-bottom: 2px solid #e5e7eb; white-space: nowrap;
}
.demo-table td { padding: 12px; border-bottom: 1px solid #eef0f2; vertical-align: top; font-size: 0.92rem; }
.demo-table tr:hover td { background: #fafbfc; }
.demo-table td:first-child { width: 28%; }
.demo-table .control-cell { width: 27%; color: #374151; }
.demo-table .row-meta { display: block; font-size: 0.78rem; color: #9aa4b2; margin-top: 3px; }
.demo-table .muted { color: #9aa4b2; }
@media (max-width: 800px) {
  .demo-table, .demo-table tbody, .demo-table tr, .demo-table td { display: block; width: auto; }
  .demo-table thead { display: none; }
  .demo-table tr { border-bottom: 1px solid #e5e7eb; padding: 8px 0; }
  .demo-table td { border: none; padding: 4px 0; }
  .demo-table td:first-child { width: auto; font-weight: 600; }
}

/* Code blocks you are meant to copy, rather than read. */
.code-copy { position: relative; }
.code-copy pre { margin-top: 0; }
.copy-btn {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  font: inherit; font-size: 0.75rem; font-weight: 600;
  padding: 4px 10px; border-radius: 6px; cursor: pointer;
  background: #fff; color: #334155; border: 1px solid #cbd5e1;
}
.copy-btn:hover { background: #f8fafc; border-color: #94a3b8; }
.copy-btn.copied { background: #dcfce7; border-color: #86efac; color: #15803d; }
/* The alternate prompts are a list rather than a block, so their button sits in
   the flow instead of being pinned to a corner. */
.alt-prompts { list-style: none; padding-left: 0; }
.alt-prompts li { margin-bottom: 8px; }
.copy-btn.copy-inline { position: static; margin-right: 8px; vertical-align: 1px; }

/* Diagrams - see figure() in src/layout.mjs. The white background is deliberate
   rather than inherited: these are exported with transparency, and a dark or
   tinted page would put the labels on top of it. */
.figure { margin: 0 0 20px; }
/* The image's own link, which wraps the img and so has to be a block. Scoped to the
   class rather than to `.figure a`: as a descendant selector it also caught links in
   the figcaption, so a word linked mid-sentence in a caption became its own line. */
.figure-link { display: block; }
.figure img {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  padding: 10px;
  box-sizing: border-box;
}
.figure-link:hover img { border-color: #94a3b8; }
.figure-link img { cursor: zoom-in; }

/* The figure lightbox - see figure() in src/layout.mjs and the handler in site.js.
   The markup is a plain link to the image file, so this is an enhancement rather
   than a requirement: with no JavaScript the link still opens the image.
   [hidden] needs restating because `display: flex` would otherwise beat it. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(15, 23, 42, 0.9);
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: 100%;
  max-height: 100%;
  /* These diagrams are exported with a transparent background, which on a dark
     overlay would put the labels on top of nothing. */
  background: #fff;
  border-radius: 8px;
  padding: 10px;
  box-sizing: border-box;
  cursor: default;
}
.lightbox-close {
  position: absolute;
  top: 14px;
  right: 18px;
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: 1.6rem;
  line-height: 1;
  color: #fff;
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.16); }
.lightbox-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
/* Stops the page scrolling behind the overlay. */
body.lightbox-open { overflow: hidden; }
.figure figcaption {
  margin-top: 8px;
  font-size: 0.8125rem;
  color: #64748b;
}

/* A card you have to open - see disclosure() in src/layout.mjs. Used where two
   alternatives are both complete and only one applies to the reader. */
.disclosure {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  margin-bottom: 12px;
  overflow: hidden;
}
.disclosure > summary {
  cursor: pointer;
  padding: 16px 22px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  list-style: none;
}
.disclosure > summary::-webkit-details-marker { display: none; }
/* The chevron, drawn rather than imported, and rotated when open. */
.disclosure > summary::before {
  content: "";
  width: 7px; height: 7px; flex-shrink: 0;
  margin-right: 4px;
  border-right: 2px solid #64748b;
  border-bottom: 2px solid #64748b;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
.disclosure[open] > summary::before { transform: rotate(45deg); }
.disclosure > summary:hover { background: #f8fafc; }
.disclosure-title { font-weight: 650; font-size: 1.0625rem; letter-spacing: -0.01em; }
.disclosure-hint { color: #64748b; font-size: 0.8125rem; }
.disclosure-body { padding: 0 22px 18px; border-top: 1px solid #eef2f6; padding-top: 16px; }
.disclosure-body > :first-child { margin-top: 0; }
.disclosure-body > :last-child { margin-bottom: 0; }

/* ---------------------------------------------------- the walkthrough page */
.wt-step { margin: 40px 0; padding-top: 4px; }
.wt-step + .wt-step { border-top: 1px solid #e5e7eb; padding-top: 32px; }
.wt-head { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 14px; }
.wt-num {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%;
  background: #1f2937; color: #fff; font-weight: 700; font-size: 0.875rem;
  display: inline-flex; align-items: center; justify-content: center; margin-top: 2px;
}
.wt-head h2 { margin: 0; font-size: 1.15rem; }
.wt-where { margin: 3px 0 0; font-size: 0.8125rem; color: #6b7280; }
.wt-kind { font-weight: 600; padding: 1px 7px; border-radius: 4px; font-size: 0.75rem; }
/* "Enforced at:" - the one line that says where in the chain a step's control sits.
   Deliberately plain and directly under the badge: the badge names the control, this
   names the place, and the demo's argument is that those are different questions. */
.wt-point { margin: 4px 0 0; font-size: 0.8125rem; color: #475569; }
.wt-point strong { color: #0f172a; }
.wt-kind.aigw { background: #fce7f3; color: #9d174d; }
.wt-kind.guardrail { background: #ffe4e6; color: #9f1239; }
.wt-kind.gwdlp { background: #dbeafe; color: #1d4ed8; }
.wt-kind.access { background: #e2e8f0; color: #334155; }
.wt-kind.mixed { background: #ede9fe; color: #6d28d9; }
.wt-kind.none { background: #f1f5f9; color: #64748b; }
.wt-step h3 {
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: #6b7280; margin: 22px 0 8px;
}
.wt-note {
  border-left: 3px solid #e5e7eb; padding: 2px 0 2px 14px; margin-top: 18px;
  font-size: 0.9rem; color: #4b5563;
}
.wt-note p { margin: 0; }

/* A hostname that is also a link: reads as code, behaves as a link. */
.host-link {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em; background: #f1f5f9; border: 1px solid #e2e8f0;
  border-radius: 4px; padding: 1px 5px; text-decoration: none; color: #0369a1;
}
.host-link:hover { background: #e0f2fe; border-color: #7dd3fc; text-decoration: none; }

/* The "with protection" half of every walkthrough step. Deliberately loud:
   it is the half the audience came for, and on a long page the eye needs
   somewhere to land. */
.wt-protected {
  background: #f0fdf4; border: 1px solid #bbf7d0; border-left: 4px solid #16a34a;
  border-radius: 8px; padding: 14px 18px; margin-top: 18px;
}
.wt-protected h3 {
  margin: 0 0 8px; color: #15803d; display: flex; align-items: center; gap: 7px;
}
.wt-protected h3 svg { width: 15px; height: 15px; fill: currentColor; }
.wt-protected p:last-child, .wt-protected ul:last-child { margin-bottom: 0; }
/* "Where to see the evidence" - inside the protected block, because the log entry
   is part of the outcome rather than a separate topic. Divided off rather than
   boxed again: a box inside a box reads as two things. */
.wt-logs {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid #bbf7d0;
}
.wt-logs h4 {
  margin: 0 0 6px;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #15803d;
}
.wt-logs ul { margin-bottom: 0; }
.wt-logs li { margin-bottom: 4px; }
/* Inline code inside a protected block, tinted to match it. Scoped the same way as
   the base inline-code rule above: unscoped, this also painted `pre > code`, so the
   JSON in a protected block got a pale green background behind pale text on a dark
   block and became unreadable. */
.wt-protected p code, .wt-protected li code, .wt-protected td code { background: #dcfce7; }
.wt-kind.swg { background: #fef3c7; color: #92400e; }
