/* Conditional Access Dojo — Security Ninja v2 theme */

:root {
  --graphite: #1A1A1C;
  --graphite-2: #222225;
  --graphite-3: #2A2A2E;
  --paper: #F5F3EF;
  --paper-dim: var(--paper);
  --paper-mute: var(--paper);
  --orange: #FF6A1A;
  /* The two ends of the SN Website hero gradient. Same tokens, same values as
     Dev Playbook/Security Ninja 2026.md — orange-hi is the light top-left end,
     orange-deep the dark bottom-right end. Added when the hero went orange;
     without them the gradient declaration was invalid and silently ignored. */
  --orange-hi: #FF8A3D;
  --orange-deep: #C84A00;
  --yellow: #F5D547;
  --line: rgba(245, 243, 239, 0.13);
  --danger: #E5484D;
  --notch: 12px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--graphite);
  color: var(--paper);
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: "Sora", sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.15;
}

h4, h5 { font-family: "Sora", sans-serif; font-weight: 700; }

a { color: var(--orange); }
a:hover { color: var(--yellow); }

.mono { font-family: "JetBrains Mono", monospace; }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 32px; }
@media (max-width: 640px) { .wrap { padding: 0 18px; } }

/* ---------- notched buttons ---------- */
.btn {
  display: inline-block;
  font-family: "Sora", sans-serif;
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 12px 22px;
  border: 0;
  cursor: pointer;
  clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% var(--notch), 100% 100%, var(--notch) 100%, 0 calc(100% - var(--notch)));
  background: var(--orange);
  color: #141414;
  transition: transform 0.15s var(--ease), background 0.15s var(--ease);
}
.btn:hover { background: var(--yellow); transform: translateY(-1px); }
.btn.ghost {
  background: transparent;
  color: var(--paper);
  box-shadow: inset 0 0 0 1.5px var(--line);
}
.btn.ghost:hover { box-shadow: inset 0 0 0 1.5px var(--orange); color: var(--orange); background: transparent; }
.btn.small { padding: 7px 14px; font-size: 0.7rem; }
.btn:focus-visible, .seg:focus-visible, .opt:focus-visible, .card-head:focus-visible, .belt-seg:focus-visible {
  outline: 2px solid var(--yellow);
  outline-offset: 2px;
}

/* ---------- dojo nav ---------- */
/* Eight dojos, one menu. Deliberately compact: it sits inside the sticky page-head
   above a hero that never shrinks, so every pixel here is a pixel of policy
   cards you don't see. Static HTML in each page rather than JS-generated —
   these pages open as file://, and a nav that needs JS to exist is a nav that
   can strand you on a stub with no way back. */
.dojo-nav {
  border-bottom: 1px solid var(--line);
  background: var(--graphite-2);
}
/* Eight tabs are a two-row menu now. Use a grid so it reads as 4 + 4 instead of
   whichever awkward natural wrap the current viewport happens to produce. */
.dojo-nav-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  min-height: 0;
  padding: 2px 0;
}
.dojo-nav-row .dojo-nav-list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  overflow-x: visible;
  scrollbar-width: none;
  min-width: 0;
}
.dojo-nav-row .dojo-nav-list::-webkit-scrollbar { display: none; }
.dojo-nav-row .dojo-tab { white-space: nowrap; }
/* Home. Occupies the slot the inert "Dojos" wordmark used to — same pixels,
   now it does something. Deliberately not a tab: it's a level up, not a
   sideways move, so it reads as a different kind of thing. */
.dojo-home {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: "Sora", sans-serif;
  font-weight: 800;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--orange);
  text-decoration: none;
  padding: 6px 10px 6px 0;
  flex-shrink: 0;
  transition: color 0.15s var(--ease);
}
.dojo-home:hover { color: var(--yellow); }
.dojo-home:focus-visible { outline: 2px solid var(--yellow); outline-offset: 2px; }
.dojo-home[aria-current="page"] { color: var(--paper); }
.home-icon { width: 15px; height: 15px; flex-shrink: 0; }

.dojo-nav-list {
  gap: 2px;
  list-style: none;
}
.dojo-tab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.54rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--paper-mute);
  padding: 3px 5px;
  border-bottom: 2px solid transparent;
  min-height: 24px;
  text-align: center;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.dojo-tab:hover { color: var(--paper); background: rgba(245, 243, 239, 0.04); }
/* The dojo you're standing in. aria-current does the work for screen readers;
   the orange underline does it for everyone else. */
.dojo-tab[aria-current="page"] {
  color: var(--paper);
  border-bottom-color: var(--orange);
  background: rgba(255, 106, 26, 0.07);
}
.dojo-tab:focus-visible { outline: 2px solid var(--yellow); outline-offset: -2px; }

.dojo-tab .soon {
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  padding: 2px 5px;
  color: var(--graphite);
  background: var(--paper-mute);
  border-radius: 2px;
}
.dojo-tab:hover .soon { background: var(--yellow); }

/* Global dojo inventory. Quiet on purpose — each dojo's own score out of 1000
   is still the progress number that actually means something. */
.dojo-nav-rollup {
  margin-left: auto;
  padding-left: 2px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  color: var(--paper-mute);
  flex-shrink: 0;
  white-space: nowrap;
}

/* The rollup yields before the tabs do. Navigation is what you came for; the
   rollup is just a nudge. */
@media (max-width: 860px) {
  .dojo-nav-rollup { display: none; }
}

@media (max-width: 860px) {
  .dojo-nav-row { grid-template-columns: auto minmax(0, 1fr); }
  .dojo-home span { display: none; }
  .dojo-tab .soon { display: none; }
}
/* Narrow screens: the tabs stop fitting cleanly. Wrapping them costs
   two extra rows of a nav that's already sitting on top of a hero that doesn't
   shrink, so scroll the strip sideways instead and keep the bar at one row.
   The rollup is the first thing to go — it's a nudge, not information you came
   for, and it isn't worth a whole row on a phone. */
@media (max-width: 640px) {
  .dojo-nav-row { display: flex; flex-wrap: nowrap; }
  .dojo-nav-row .dojo-nav-list {
    display: flex;
    grid-template-columns: none;
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .dojo-nav-list li { flex: 0 0 auto; }
  .dojo-nav-list::-webkit-scrollbar { display: none; }
  .dojo-tab { white-space: nowrap; }
  .dojo-nav-rollup { display: none; }
}

/* ---------- header ---------- */
/* Hero height is deliberately tight. The head is sticky, so every pixel here is
   a pixel of content the reader never gets to see — on a 900px laptop the old
   hero plus scoreboard took 617px and left under a third of the screen for the
   actual dojo.

   Two different things set the height depending on the page, which is why both
   had to come down: on a page whose h1 wraps to two lines (Conditional Access)
   the TEXT is the constraint; on a one-line title the 240px cat was the floor.
   Trimming only one would have fixed only half the pages. */
/* ---------- hero: the v2 orange plate ----------
   Lifted from the SN Website 2026 theme (Dev Playbook/Security Ninja 2026.md),
   which is the same design system this tool's palette came from:

     linear-gradient(135deg, #ff8a3d 0%, #ff6a1a 45%, #c84a00 100%)
     + 48px grid overlay, 1px black at 8%, masked to bottom so it fades in

   Two notes from that spec worth keeping:
   - NO dark radial overlays. They were tried on the site and removed for
     looking dirty. If this ever needs calming down, lower the grid opacity
     rather than washing it with black.
   - On orange, buttons and accents INVERT: dark plate, orange or dark text.
     Anything that was orange on graphite has to become dark here or it
     disappears into the background. */
.hero {
  min-height: 128px;
  padding: 18px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.22);
  position: relative;
  overflow: visible;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.08) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.2));
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.2));
}
.hero > .wrap { position: relative; z-index: 1; }
.hero-grid {
  display: flex;
  align-items: center;
  min-height: 90px;
  padding-right: 160px;
}
.hero-copy { min-width: 0; }

/* The art is a black-on-black PNG. Screen blending drops the black box into the
   background so no seam shows, and the cat reads as a shadow.

   THAT ONLY WORKS ON A DARK GROUND, which is why the cat now sits on its own
   graphite plate inside the orange hero rather than directly on the orange.
   I checked this rather than assuming: composited on the orange gradient, the
   screen blend leaves literally zero pixels darker than the background — the
   cat vanishes completely. A luminance cut-out fails too, and so does a
   flood-fill silhouette, because the artwork is near-black with only light
   highlights: the fill leaks through the outline and hollows the body out.
   The asset is dark-on-dark by design and cannot sit on orange.

   The plate is on-brand rather than a workaround — v2's whole language is
   bevelled rack panels, so a graphite plate on an orange bay reads as
   deliberate. If the SN Website's ninja-cat-v3.png (transparent, coloured,
   baked drop shadow) is dropped into images/, this plate can go and the cat
   can sit straight on the orange like it does on the site. */
.hero-art {
  position: absolute;
  top: 50%;
  right: 32px;
  z-index: 3;
  width: 128px;
  margin: 0;
  line-height: 0;
  transform: translateY(-50%);
}
.hero-art img {
  width: 100%;
  height: auto;
}
/* The cat's belt, tinted to match your current rank. Position is a % of the image
   box, so it tracks the image at any size.
   The mask is a pre-cut alpha silhouette of just the belt fabric (the ridged
   straps either side of the buckle) — the silver buckle itself is punched out
   to alpha 0, so it always stays metal. A solid rank-coloured fill is clipped
   to that silhouette, so this reads as the belt fabric actually being that
   colour (opaque, textured by the mask's own shading) rather than a
   translucent wash sitting over the art.
   The mask is inlined as a base64 data URI rather than url(images/belt-mask.png)
   deliberately: this file is opened directly as file:// (no local server), and
   Chrome treats file:// as an opaque origin — it silently refuses to fetch a
   CSS mask-image from a separate file under that origin (CORS), even from the
   same folder, even though a plain <img src="..."> to the same path works
   fine. The computed style looks completely correct (opacity, background,
   mask-image URL all report as set) but nothing paints, because the mask
   resource itself never loaded. A data: URI has no separate fetch, so it
   isn't subject to that restriction. Confirmed with a real headless-Chrome
   render opened via file://, not just computed-style inspection. */
.cat-belt-tint {
  position: absolute;
  left: 47.69%;
  top: 60.21%;
  width: 9.09%;
  height: 8.45%;
  background: var(--belt-tint, transparent);
  -webkit-mask-image: url(data:image/png;base64,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);
  mask-image: url(data:image/png;base64,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);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  opacity: 0;
  transition: opacity 0.5s var(--ease), background 0.5s var(--ease);
  pointer-events: none;
}
.cat-belt-tint.earned { opacity: 0.96; }
.hero h1 {
  font-size: clamp(3rem, 3.6vw, 3.4rem);
  line-height: 1;
  color: var(--paper);
  overflow-wrap: anywhere;
}
.hero h1 em { font-style: normal; color: var(--paper); }

.page-overview {
  display: block;
  max-width: 82ch;
  padding: 10px 0 11px;
  border-bottom: 1px solid var(--line);
  color: var(--paper-dim);
  font-size: 0.88rem;
  line-height: 1.45;
}
.page-overview-credit {
  margin-top: 7px;
  color: var(--paper-mute);
  font-size: 0.78rem;
}
.page-overview a {
  color: var(--orange);
  text-underline-offset: 2px;
}

/* The landing page has no scoreboard for the cat to span, so its title row
   provides the full compact art height itself. */
.dojo-landing .hero { min-height: 150px; }

/* ---------- sticky page head (hero + scoreboard) ---------- */
/* Both stay put, full size, permanently — only the main content and footer
   scroll underneath. Fixed size on a sticky element (no shrink-on-scroll) is
   deliberate: animating a sticky element's own height while the user scrolls
   changes the page's scroll geometry every frame, which the browser's scroll
   anchoring then fights — that's a visible shake, not a look. */
/* The orange plate spans the hero AND the scoreboard, so the gradient lives
   here rather than on .hero — one continuous 135deg sweep across the whole
   sticky head instead of two that meet at a seam. The nav keeps its own
   graphite fill on top, which gives the plate a lid. */
.page-head {
  position: sticky;
  top: 0;
  z-index: 40;
  background: linear-gradient(135deg, var(--orange-hi) 0%, var(--orange) 45%, var(--orange-deep) 100%);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.35);
  overflow-anchor: none;
}

/* Sits on the orange plate now (gradient is on .page-head). Keep every header
   label high-contrast against both the graphite navigation and orange score
   plate. The completed white-belt tile gets the sole dark-text exception below. */
.scoreboard {
  border-bottom: 1px solid rgba(0, 0, 0, 0.28);
  min-height: 46px;
  padding: 4px 0;
}
.page-head .dojo-home,
.page-head .dojo-tab,
.page-head .dojo-nav-rollup,
.page-head .hero h1,
.page-head .hero h1 em,
.page-head .kpi .kpi-label,
.page-head .kpi .kpi-value,
.page-head .kpi .kpi-value small,
.page-head .kpi.rank .kpi-value,
.page-head .belt-seg .belt-seg-label,
.page-head .mini-stats,
.page-head .mini-stats b,
.page-head .scoreboard .btn.ghost {
  color: var(--paper);
}
.page-head .belt-seg .belt-seg-label {
  mix-blend-mode: normal;
}
.page-head .belt-seg.done[data-belt="white"] .belt-seg-label {
  color: #0e0e10;
}
.scoreboard .btn.ghost {
  box-shadow: inset 0 0 0 1.5px rgba(245, 243, 239, 0.72);
}
.scoreboard .btn.ghost:hover {
  color: var(--paper);
  background: rgba(14, 14, 16, 0.2);
  box-shadow: inset 0 0 0 1.5px var(--paper);
}
/* One row at laptop widths. This wrapped before: the five children needed
   1142px inside a 1080px row, so "Start over" dropped to a line of its own and
   took ~60px of the sticky head with it — dead space on every page, above the
   fold, permanently. Trimming the gap and the KPI padding buys back the 62px.
   Below 1100 it's allowed to wrap; there genuinely isn't room. */
.scoreboard .row {
  display: grid;
  grid-template-columns: minmax(80px, 0.78fr) minmax(96px, 0.92fr) minmax(170px, 1fr) auto auto;
  align-items: center;
  gap: 6px;
  padding-right: 116px;
}

.kpi {
  border-radius: 4px;
  background: linear-gradient(160deg, var(--graphite-3), var(--graphite-2));
  border: 1px solid var(--line);
  border-top-color: rgba(245, 243, 239, 0.28);
  border-left-color: rgba(245, 243, 239, 0.2);
  padding: 2px 5px 3px;
  min-width: 0;
}
.kpi .kpi-label {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.4rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper-mute);
  white-space: nowrap;
}
.kpi .kpi-value {
  font-family: "JetBrains Mono", monospace;
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--paper);
  line-height: 1.1;
}
.kpi .kpi-value small { font-size: 0.8rem; color: var(--paper-mute); font-weight: 400; }
.kpi.rank .kpi-value { font-size: 0.66rem; color: var(--orange); text-transform: uppercase; font-family: "Sora", sans-serif; }

.mini-stats {
  display: flex;
  grid-column: 4;
  grid-row: 1;
  flex-wrap: nowrap;
  gap: 6px;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.54rem;
  color: var(--paper-dim);
  white-space: nowrap;
}
.mini-stats b { color: var(--paper); }

#btn-reset { margin-left: auto; flex-shrink: 0; }
.scoreboard .row #btn-reset {
  grid-column: 5;
  grid-row: 1;
  align-self: center;
  justify-self: end;
  margin-left: 0;
  min-height: 0;
  padding: 4px 7px;
  font-size: 0.54rem;
}

/* ---------- belt rail (signature) ---------- */
.belt-rail {
  display: flex;
  grid-column: 3;
  grid-row: 1;
  gap: 4px;
  flex: 1;
  width: 100%;
  min-width: 0;
  height: 26px;
}
.belt-seg {
  /* These are <button> elements now (clickable — see below), so reset the UA
     button defaults before the real styling below applies. */
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  padding: 0;
  font: inherit;

  position: relative;
  flex: 1;
  background: var(--graphite-3);
  border: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  overflow: visible;
  cursor: pointer;
  transition: background 0.4s var(--ease), transform 0.15s var(--ease), border-color 0.15s var(--ease);
}
.belt-seg:hover {
  border-color: var(--belt);
  transform: translateY(-1px);
}
.belt-seg:active { transform: translateY(0); }
.belt-seg.done {
  background: var(--belt);
  border-color: var(--belt);
  box-shadow: inset 0 -6px 0 rgba(0, 0, 0, 0.22), inset 0 3px 0 rgba(255, 255, 255, 0.14);
}
.belt-seg .belt-seg-label {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--paper-mute);
  mix-blend-mode: difference;
}
/* Always-on colour chip so you can see every belt's colour up front,
   not just the ones you've earned. */
.belt-seg .belt-chip {
  width: 18px;
  height: 4px;
  background: var(--belt);
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3);
}
.belt-seg.done .belt-chip { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35); }
.belt-seg .knot {
  position: absolute;
  right: -6px;
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
  width: 11px;
  height: 11px;
  background: var(--belt);
  border: 2px solid var(--graphite);
  z-index: 2;
}

/* ---------- stub (dojo not open yet) ---------- */
.stub { margin: 34px 0 8px; }
.stub-flag {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.65rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--graphite);
  background: var(--yellow);
  padding: 4px 9px;
  display: inline-block;
  margin-bottom: 12px;
}
.stub h2 { font-size: 1.15rem; margin-bottom: 8px; }
.stub > p { color: var(--paper-dim); font-size: 0.95rem; max-width: 70ch; }
.stub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
  margin: 22px 0;
}
.stub-card {
  background: var(--graphite-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--orange);
  padding: 18px 20px;
}
.stub-card h3 { font-size: 0.9rem; margin-bottom: 8px; color: var(--paper); }
.stub-card p { color: var(--paper-dim); font-size: 0.88rem; line-height: 1.65; }
.stub-card em { color: var(--paper); font-style: normal; font-weight: 600; }
.stub-foot {
  border-left: 3px solid var(--yellow);
  background: var(--graphite-2);
  padding: 14px 18px;
  color: var(--paper-dim);
  font-size: 0.9rem;
  max-width: 75ch;
}

/* ---------- break-glass banner + step 0 ---------- */
.banner {
  background: rgba(229, 72, 77, 0.12);
  border: 1px solid rgba(229, 72, 77, 0.5);
  border-left: 4px solid var(--danger);
  padding: 12px 18px;
  margin: 26px 0 0;
  font-size: 0.92rem;
}
.banner a { color: var(--yellow); }

.step0 {
  margin-top: 26px;
  border: 1px dashed rgba(255, 106, 26, 0.55);
  background: var(--graphite-2);
  padding: 22px 24px;
}
.step0.confirmed { border-style: solid; border-color: rgba(76, 175, 125, 0.6); }
.step0 h3 { font-size: 1rem; color: var(--orange); margin-bottom: 8px; }
.step0.confirmed h3 { color: #4CAF7D; }
.step0 p { color: var(--paper-dim); font-size: 0.95rem; max-width: 75ch; }
.step0 ul { margin: 12px 0 14px 20px; color: var(--paper-dim); font-size: 0.92rem; }
.step0 label {
  display: flex;
  gap: 10px;
  align-items: center;
  font-weight: 600;
  cursor: pointer;
}
.step0 input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--orange); cursor: pointer; }
.step0 .step0-status {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.75rem;
  color: var(--paper-mute);
  margin-left: 8px;
}
.step0-note {
  max-width: 78ch;
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid rgba(245, 213, 71, 0.38);
  border-left: 3px solid var(--yellow);
  background: rgba(245, 213, 71, 0.07);
  color: var(--paper-dim);
  font-size: 0.84rem;
  line-height: 1.58;
}
.step0-note strong,
.step0-note a { color: var(--yellow); }
.step0.step0-collapsible { padding: 0; }
.step0-collapsible summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  cursor: pointer;
  list-style: none;
}
.step0-collapsible summary::-webkit-details-marker { display: none; }
.step0-collapsible summary::after {
  content: "+";
  margin-left: auto;
  color: var(--yellow);
  font-family: "JetBrains Mono", monospace;
  font-size: 1.1rem;
  line-height: 1;
}
.step0-collapsible[open] summary::after { content: "-"; }
.step0-summary-title {
  color: var(--orange);
  font-family: "Sora", sans-serif;
  font-size: 0.94rem;
  font-weight: 700;
}
.step0-summary-hint {
  color: var(--paper-mute);
  font-family: "JetBrains Mono", monospace;
  font-size: 0.64rem;
  margin-left: auto;
}
.step0-collapsible .step0-body { padding: 0 24px 22px; }
.step0-collapsible .step0-body > :first-child { margin-top: 0; }
.step0-collapsible summary:focus-visible {
  outline: 2px solid var(--yellow);
  outline-offset: -3px;
}

/* ---------- questionnaire ---------- */
.questionnaire { margin: 32px 0 8px; }
.questionnaire h2 { font-size: 1.15rem; margin-bottom: 6px; }
.questionnaire > p { color: var(--paper-dim); margin-bottom: 14px; font-size: 0.95rem; }
/* Grid default (align-items: stretch) — every card in a row matches its tallest
   sibling, so rows read as tidy, even blocks. This only looks good because the
   licence card spans two columns (below): that keeps it to two rows of buttons
   instead of five, so the height it sets for row 1 stays reasonable rather than
   dragging its neighbour down with a slab of empty space. */
.q-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 10px; }
.q {
  background: var(--graphite-2);
  border: 1px solid var(--line);
  padding: 12px 14px;
}
/* Licence has more than double the options of any other question — give it two
   columns' worth of width so its buttons wrap into rows of 4+ instead of 2,
   rather than growing tall and dragging the grid row down with it. */
.q.q-wide { grid-column: span 2; }
@media (max-width: 640px) { .q.q-wide { grid-column: span 1; } }
.q p { font-weight: 600; font-size: 0.88rem; margin-bottom: 8px; }
.q .opts { display: flex; flex-wrap: wrap; gap: 6px; }
.opt {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  padding: 6px 10px;
  background: transparent;
  color: var(--paper-dim);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: all 0.15s var(--ease);
}
.opt:hover { border-color: var(--orange); color: var(--paper); }
.opt.active { background: var(--orange); border-color: var(--orange); color: #141414; font-weight: 700; }

/* Footnote under a question, for when the honest answer is "it's complicated".
   Used on the Email Dojo's Defender for Office 365 question, where Microsoft's
   own docs contradict each other about what E3 includes. */
.q-note {
  font-size: 0.75rem !important;
  font-weight: 400 !important;
  color: var(--paper-mute);
  line-height: 1.5;
  margin: 8px 0 0 !important;
  max-width: 70ch;
}
.q-note em { color: var(--paper-dim); font-style: italic; }

/* ---------- step 0.5 — passwordless readiness ---------- */
.readiness {
  margin: 28px 0 8px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--yellow);
  background: var(--graphite-2);
  padding: 22px 24px;
}
.readiness h3 { font-size: 1rem; color: var(--yellow); margin-bottom: 8px; }
.ready-lede { color: var(--paper-dim); font-size: 0.95rem; max-width: 75ch; margin-bottom: 18px; }

.ready-flag {
  background: rgba(255, 106, 26, 0.1);
  border: 1px solid rgba(255, 106, 26, 0.45);
  padding: 12px 16px;
  margin-bottom: 20px;
  font-size: 0.9rem;
}
.ready-flag strong {
  font-family: "Sora", sans-serif;
  display: block;
  color: var(--orange);
  margin-bottom: 4px;
}
.ready-flag p { color: var(--paper-dim); max-width: 75ch; }

.ready-group { margin-bottom: 22px; }
.ready-group:last-child { margin-bottom: 0; }
.ready-group h4 {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--orange);
  padding-bottom: 8px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.ready-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.ready-item {
  background: var(--graphite-3);
  border: 1px solid var(--line);
  padding: 14px 16px;
  transition: border-color 0.2s var(--ease);
}
.ready-item:hover { border-color: rgba(245, 213, 71, 0.5); }
.ready-item h5 { font-size: 0.88rem; margin-bottom: 6px; }
.ready-item p { color: var(--paper-dim); font-size: 0.87rem; line-height: 1.6; }
.ready-item a {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  display: inline-block;
  margin-top: 8px;
}

/* ---------- identity model designer ---------- */
.designer {
  margin: 28px 0 8px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--orange);
  background: var(--graphite-2);
  padding: 22px 24px;
}
.designer h3 { font-size: 1rem; color: var(--orange); margin-bottom: 8px; }
.designer .ready-lede em { color: var(--paper); font-style: normal; font-weight: 600; }
.design-gate {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.78rem;
  color: var(--paper-mute);
  border: 1px dashed var(--line);
  padding: 20px;
  text-align: center;
}

/* The tiers. Colour carries the argument here: the control plane is the loud
   one, the protected zone is the resolution. Same graphite → orange → yellow
   arc the brand uses elsewhere. */
.tier {
  border: 1px solid var(--line);
  border-left: 3px solid var(--paper-mute);
  background: var(--graphite);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.tier-t0 { border-left-color: var(--danger); }
.tier-t1 { border-left-color: var(--orange); }
.tier-t2 { border-left-color: rgba(245, 243, 239, 0.44); }
.tier-rp { border-left-color: var(--yellow); }
.tier-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.tier-head h4 { font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.02em; }
.tier-t0 .tier-head h4 { color: var(--danger); }
.tier-t1 .tier-head h4 { color: var(--orange); }
.tier-rp .tier-head h4 { color: var(--yellow); }
.tier-strap {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  color: var(--paper-mute);
}
/* Model items are full cards now, not sentences — same expand-for-depth
   behaviour as a policy card, so they stack rather than sit in a grid. */
.tier-cards { display: flex; flex-direction: column; gap: 8px; }
.card.mcard { --belt: var(--orange); }
.tier-t0 .card.mcard { --belt: var(--danger); }
.tier-rp .card.mcard { --belt: var(--yellow); }
.card.mcard .card-title .chip-row { margin-top: 8px; gap: 5px; }
code.obj {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  background: var(--graphite);
  border: 1px solid var(--line);
  color: var(--orange);
  padding: 3px 7px;
  display: inline-block;
}
/* Object chips carry the official Microsoft icon for what they are — an
   administrative unit looks like an administrative unit, a group looks like a
   group. Microsoft's artwork keeps its own colours (recolouring is the one
   thing the licence actually forbids), so the chip's TEXT does the tier
   signalling and the icon stays as shipped. */
code.obj.has-glyph {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px 3px 6px;
  border-color: rgba(245, 243, 239, 0.16);
  color: var(--paper-dim);
}
.obj-glyph { width: 15px; height: 15px; flex-shrink: 0; }

/* The sprite holds every symbol once. It renders nothing itself — but it must
   stay in the document and must NOT be display:none in a way that detaches it,
   or every <use> that references it resolves to nothing. */
.ms-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Tier signalling moves to the chip border and label, since the icon can't be
   tinted. Protected objects still read yellow, delegation boundaries orange. */
code.obj[data-g="administrativeUnits"] { border-color: rgba(255, 106, 26, 0.35); }
.tier-rp code.obj[data-g="administrativeUnits"] { border-color: rgba(245, 213, 71, 0.45); color: var(--yellow); }
code.obj[data-g="users"] { border-color: rgba(245, 243, 239, 0.16); }
.tier-t0 code.obj[data-g="users"] { border-color: rgba(229, 72, 77, 0.35); }

.design-flags { margin: 16px 0; }
.design-notes { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px; margin: 16px 0; }
.design-note {
  background: var(--graphite);
  border: 1px solid var(--line);
  border-left: 3px solid var(--yellow);
  padding: 12px 14px;
}
.design-note h5 { font-size: 0.82rem; margin-bottom: 5px; color: var(--yellow); }
.design-note p { color: var(--paper-dim); font-size: 0.83rem; line-height: 1.6; }

.design-sub {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--orange);
  padding-bottom: 8px;
  margin: 22px 0 12px;
  border-bottom: 1px solid var(--line);
}
.obj-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.obj-table th {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--paper-mute);
  text-align: left;
  padding: 6px 10px 6px 0;
  border-bottom: 1px solid var(--line);
}
.obj-table td { padding: 8px 10px 8px 0; border-bottom: 1px solid var(--line); color: var(--paper-dim); vertical-align: top; }
.obj-table code { font-family: "JetBrains Mono", monospace; font-size: 0.75rem; color: var(--orange); }
.design-foot { margin-top: 14px; font-size: 0.82rem; color: var(--paper-mute); line-height: 1.65; }
.design-foot code { font-family: "JetBrains Mono", monospace; font-size: 0.72rem; color: var(--paper-dim); }

.banner-info {
  background: rgba(245, 213, 71, 0.08);
  border-color: rgba(245, 213, 71, 0.45);
  border-left-color: var(--yellow);
}

/* ---------- card diagram ---------- */
/* Only a handful of controls carry one. The bar is "prose genuinely struggles
   here" — not decoration. Inline SVG, so it inherits the brand tokens below and
   never fetches anything (see the note in core.js about file:// and CORS). */
.card-diagram {
  margin: 16px 0 6px;
  padding: 16px 18px;
  background: var(--graphite);
  border: 1px solid var(--line);
  border-left: 3px solid var(--orange);
  /* Narrow screens scroll the diagram rather than squashing it into
     illegibility — a 700px flow diagram at 320px wide is not a diagram. */
  overflow-x: auto;
}
.card-diagram svg {
  display: block;
  width: 100%;
  height: auto;
  min-width: 560px;
}
.card-diagram figcaption {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  color: var(--paper-mute);
  margin-top: 10px;
  min-width: 560px;
}

/* ---------- belt sections ---------- */
.belt-section { margin: 46px 0; }
.belt-header { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.belt-band {
  width: 46px;
  height: 16px;
  background: var(--belt);
  box-shadow: inset 0 -5px 0 rgba(0, 0, 0, 0.25), inset 0 2px 0 rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(245, 243, 239, 0.18);
}
.belt-header h3 { font-size: 1.15rem; }
.belt-header h3 em {
  display: block;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-style: normal;
  font-weight: 500;
  font-size: 0.85rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--paper-mute);
  margin-top: 2px;
}
.belt-earned {
  margin-left: auto;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #4CAF7D;
  border: 1px solid rgba(76, 175, 125, 0.5);
  padding: 4px 10px;
}

/* ---------- policy cards ---------- */
.cards { display: flex; flex-direction: column; gap: 12px; }
.card {
  border-radius: 4px;
  background: var(--graphite-2);
  border: 1px solid var(--line);
  border-left: 4px solid var(--belt);
  transition: border-color 0.2s var(--ease);
}
/* Enforced cards keep their own belt colour (already set via var(--belt)) —
   no separate "done" colour override, so White stays white, Blue stays blue, etc. */
.card.na { opacity: 0.55; }
.card,
.card-head,
.card-title,
.card-meta,
.policy-name,
.chip-row {
  min-width: 0;
}
.card-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
  cursor: pointer;
}
.card-head:hover h4 { color: var(--orange); }
.card-title .code {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.68rem;
  color: var(--orange);
  letter-spacing: 0.1em;
}
.card-title h4 { font-size: 1rem; margin: 2px 0 4px; transition: color 0.15s var(--ease); }
.card-title .one-liner { color: var(--paper-dim); font-size: 0.88rem; max-width: 62ch; }

/* full policy name — the exact string to type into Entra */
.policy-name { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.policy-name code {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem;
  color: var(--paper-dim);
  background: var(--graphite);
  border: 1px solid var(--line);
  padding: 5px 9px;
  user-select: all;
  cursor: text;
}
.card.na .policy-name code { opacity: 0.5; }
.name-copy {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 5px 9px;
  background: transparent;
  color: var(--paper-mute);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: all 0.15s var(--ease);
}
.name-copy:hover { border-color: var(--orange); color: var(--orange); }
.card-meta { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.pts { font-family: "JetBrains Mono", monospace; font-size: 0.75rem; color: var(--paper-mute); padding-top: 4px; white-space: nowrap; }
.chev { color: var(--paper-mute); transition: transform 0.2s var(--ease); padding-top: 2px; }
.card.open .chev { transform: rotate(180deg); }

.chip {
  display: inline-block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  padding: 4px 9px;
  border: 1px solid var(--line);
  color: var(--paper-dim);
  text-decoration: none;
  white-space: nowrap;
}
.chip.licence { border-color: rgba(255, 196, 46, 0.4); color: var(--yellow); }
.chip.skip { border-color: rgba(229, 72, 77, 0.45); color: #f08a8d; white-space: normal; }
.chip.mitre { border-color: rgba(255, 106, 26, 0.4); }
.chip.mitre:hover { border-color: var(--orange); color: var(--orange); }

.card-body { padding: 4px 20px 18px; border-top: 1px solid var(--line); }
.card-body h5 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--orange);
  margin: 18px 0 6px;
}
.card-body p { color: var(--paper-dim); font-size: 0.93rem; max-width: 78ch; }
.card-body ol { margin: 4px 0 0 20px; color: var(--paper-dim); font-size: 0.93rem; }
.card-body ol li { margin-bottom: 5px; }
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.ref { margin-top: 14px; font-size: 0.88rem; }
.card-actions { margin-top: 16px; display: flex; align-items: center; gap: 12px; }
.copy-note { font-family: "JetBrains Mono", monospace; font-size: 0.72rem; color: #4CAF7D; }
.json-note { margin-top: 14px; font-size: 0.85rem; color: var(--paper-mute); font-style: italic; }

.card-foot { padding: 12px 20px 16px; }
.seg-group { display: inline-flex; border: 1px solid var(--line); }
.seg {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem;
  padding: 8px 14px;
  background: transparent;
  border: 0;
  color: var(--paper-dim);
  cursor: pointer;
  transition: all 0.15s var(--ease);
}
.seg + .seg { border-left: 1px solid var(--line); }
.seg:hover:not(:disabled) { color: var(--paper); background: var(--graphite-3); }
.seg.active { background: var(--orange); color: #141414; font-weight: 700; }
/* Enforced uses the policy's own belt colour, not a fixed "done" green — matches
   the card's left border, the belt rail chips and the cat's belt tint. */
.seg.active:last-child { background: var(--belt); }
.seg:disabled { cursor: not-allowed; opacity: 0.4; }

/* ---------- outputs ---------- */
.outputs {
  margin: 60px 0;
  border: 1px solid var(--line);
  background: var(--graphite-2);
  padding: 28px;
}
.outputs h2 { font-size: 1.2rem; margin-bottom: 8px; }
.outputs p { color: var(--paper-dim); max-width: 70ch; margin-bottom: 18px; font-size: 0.95rem; }
.outputs .out-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* ---------- footer ---------- */
.foot {
  border-top: 1px solid var(--line);
  padding: 26px 0 40px;
  color: var(--paper-mute);
  font-size: 0.82rem;
}
.foot a { color: var(--paper-dim); }
.foot .legal-disclaimer {
  max-width: 92ch;
  margin-top: 14px;
  color: var(--paper);
  line-height: 1.65;
}

/* ---------- toast ---------- */
#toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 20px);
  background: var(--paper);
  color: #141414;
  font-family: "Sora", sans-serif;
  font-weight: 700;
  font-size: 0.85rem;
  padding: 12px 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
  clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% var(--notch), 100% 100%, var(--notch) 100%, 0 calc(100% - var(--notch)));
  max-width: min(90vw, 520px);
  z-index: 60;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- responsive ---------- */

@media (max-width: 1024px) {
  .questionnaire,
  .readiness,
  .designer,
  .outputs,
  .belt-section {
    margin-top: 28px;
  }

  .step0,
  .readiness,
  .designer,
  .outputs {
    padding: 18px;
  }

  .q-grid,
  .ready-items,
  .design-notes,
  .stub-grid {
    grid-template-columns: 1fr;
  }

  .q.q-wide {
    grid-column: span 1;
  }

  .opt,
  .seg,
  .btn {
    min-height: 42px;
  }

  .opt {
    display: inline-flex;
    align-items: center;
  }

  .belt-header {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 10px;
  }

  .belt-earned {
    margin-left: 0;
  }

  .card-head {
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px;
  }

  .card-title h4 {
    font-size: 0.95rem;
    overflow-wrap: anywhere;
  }

  .card-title .one-liner,
  .card-body p,
  .card-body ol {
    font-size: 0.9rem;
  }

  .card-meta {
    justify-content: flex-start;
    width: 100%;
  }

  .card-meta .chip,
  .chip-row .chip,
  .policy-name code {
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .policy-name {
    align-items: stretch;
  }

  .policy-name code {
    flex: 1 1 100%;
  }

  .name-copy {
    min-height: 36px;
  }

  .card-body {
    padding: 4px 16px 16px;
  }

  .card-actions,
  .outputs .out-row {
    align-items: stretch;
    flex-wrap: wrap;
  }

  .seg-group {
    display: flex;
    flex-wrap: wrap;
    max-width: 100%;
  }

  .seg {
    flex: 1 1 auto;
  }

  .obj-table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media (max-width: 720px) {
  .card-head { flex-direction: column; gap: 10px; }
  .card-meta { justify-content: flex-start; }
}

@media (min-width: 701px) and (max-width: 1024px) {
  .hero {
    min-height: 84px;
    padding: 14px 0;
  }

  .hero-grid {
    min-height: 56px;
    padding-right: 140px;
  }

  .hero-art {
    width: 90px;
  }

  .hero h1 {
    font-size: clamp(2rem, 4vw, 2.5rem);
  }

  .dojo-landing .hero { min-height: 104px; }
}

@media (max-width: 700px) {
  .hero {
    min-height: 56px;
    padding: 7px 0 6px;
  }

  .dojo-landing .hero { min-height: 59px; }

  .wrap.hero-grid {
    padding-right: 82px;
    min-height: 42px;
  }

  .hero-art {
    top: 50%;
    right: 18px;
    width: 56px;
    transform: translateY(-50%);
  }

  .hero h1 {
    font-size: clamp(1.08rem, 4.8vw, 1.22rem);
  }

  .scoreboard .row {
    grid-template-columns: minmax(84px, 1fr) minmax(78px, 0.9fr) auto minmax(72px, 0.9fr);
    grid-template-rows: auto 22px;
    column-gap: 4px;
    row-gap: 2px;
    padding-right: 0;
  }

  .scoreboard {
    padding: 1px 0;
  }

  .kpi {
    padding: 1px 4px 2px;
  }

  .kpi .kpi-label {
    font-size: 0.4rem;
    line-height: 1;
  }

  .mini-stats {
    grid-column: 4;
    grid-row: 1;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 0;
    font-size: 0.46rem;
    line-height: 1.1;
  }

  .belt-rail {
    grid-column: 1 / -1;
    grid-row: 2;
    width: auto;
    height: 22px;
  }

  .scoreboard .row #btn-reset {
    grid-column: 3;
    grid-row: 1;
    align-self: stretch;
    justify-self: stretch;
    min-height: 0;
    padding: 4px 5px;
    font-size: 0.52rem;
  }
}

@media (max-width: 520px) {
  .wrap {
    padding: 0 18px;
  }

  .step0-collapsible summary { padding: 14px 16px; }
  .step0-summary-title { font-size: 0.88rem; }
  .step0-summary-hint { display: none; }
  .step0-collapsible .step0-body { padding: 0 16px 16px; }

  .dojo-nav-row {
    min-height: 36px;
  }

  .dojo-tab {
    min-height: 32px;
    padding: 5px 7px;
  }

  .belt-seg {
    gap: 5px;
  }

  .belt-seg .belt-seg-label {
    font-size: 0.48rem;
  }

  .questionnaire,
  .readiness,
  .designer,
  .outputs,
  .belt-section,
  .mats,
  .how,
  .purpose {
    margin-top: 26px;
  }

  .step0,
  .readiness,
  .designer,
  .outputs {
    padding: 16px;
  }

  .q {
    padding: 12px;
  }

  .q .opts,
  .card-actions,
  .outputs .out-row {
    flex-direction: column;
  }

  .opt,
  .card-actions .btn,
  .outputs .out-row .btn {
    justify-content: center;
    width: 100%;
  }

  .card-foot {
    padding: 12px 16px 16px;
  }

  .seg-group {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    width: 100%;
  }

  .seg {
    justify-content: center;
    padding: 9px 8px;
  }

  .seg + .seg {
    border-left: 1px solid var(--line);
  }

  .card-diagram {
    padding: 14px;
  }

  .card-diagram svg,
  .card-diagram figcaption {
    min-width: 520px;
  }

  .mat-grid,
  .purpose-grid,
  .how-grid {
    grid-template-columns: 1fr;
  }

  .mat {
    padding: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  html { scroll-behavior: auto; }
}

/* The architecture diagram carries the official Microsoft Entra icons. It lives
   inside its own card body like every other piece of depth in these dojos. */
.arch-diagram { border-left-color: var(--yellow); }
.arch-diagram svg { min-width: 640px; }
.tier.tier-arch { border-left-color: var(--yellow); }
.tier-arch .card.mcard { --belt: var(--yellow); }

/* Official Microsoft product icon on a policy card head, sat with the code
   badge. Artwork stays exactly as Microsoft ships it — no recolour — so it
   reads as "this is the product you'll be configuring". */
.policy-icon {
  display: inline-flex;
  align-items: center;
  margin-right: 7px;
  vertical-align: -3px;
}
.policy-icon svg { width: 15px; height: 15px; display: block; }

/* ---------- landing page ---------- */
.purpose { margin: 34px 0 8px; }
.section-kicker {
  font-family: "JetBrains Mono", monospace;
  color: var(--orange);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.purpose-lede {
  max-width: 82ch;
  color: var(--paper-dim);
  font-size: 0.98rem;
  line-height: 1.68;
  margin-bottom: 18px;
}
.purpose-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 12px;
}
.purpose-card {
  background: var(--graphite-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--orange);
  padding: 16px 18px;
}
.purpose-card h3 { font-size: 0.88rem; margin-bottom: 8px; color: var(--paper); }
.purpose-card p { color: var(--paper-dim); font-size: 0.86rem; line-height: 1.64; }

.mats { margin: 34px 0 8px; }
.mats h2 { font-size: 1.15rem; margin-bottom: 6px; }
.mats-lede { color: var(--paper-dim); font-size: 0.95rem; max-width: 72ch; margin-bottom: 20px; }

/* FIVE dojos now, so this is three across, not four.

   Four columns with five cards gives 4 + 1, and a single card stranded on its
   own row reads exactly like "and one more we bolted on" — which is precisely
   what it isn't. Three across gives 3 + 2, which looks deliberate, and the
   wider card earns its keep: these descriptions are two lines instead of four.

   The maths, because I got it wrong once at four columns: .wrap is max-width
   1080 with 32px of padding each side, so the real content box is 1016px.
   Three columns plus two 12px gaps means each card can be at most
   (1016 - 24) / 3 = 330px. 300 leaves headroom and still can't fit a fourth
   (4 x 300 + 36 = 1236 > 1016), so it can't silently reflow to 4 + 1.

   If a sixth dojo ever lands, this becomes 3 + 3 with no change needed. */
.mat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 12px;
}
@media (max-width: 1000px) { .mat-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px)  { .mat-grid { grid-template-columns: 1fr; } }

/* The whole card is the link. A card with a button inside it has two targets
   and one of them is wrong. */
.mat {
  display: flex;
  flex-direction: column;
  background: var(--graphite-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--orange);
  padding: 18px 20px 16px;
  text-decoration: none;
  transition: transform 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.mat:hover {
  transform: translateY(-2px);
  background: var(--graphite-3);
  border-color: rgba(255, 106, 26, 0.5);
  border-top-color: var(--yellow);
}
.mat:focus-visible { outline: 2px solid var(--yellow); outline-offset: 2px; }

.mat-head { display: flex; align-items: center; gap: 11px; margin-bottom: 10px; }
.mat-icon { display: inline-flex; flex-shrink: 0; }
.mat-icon svg { width: 26px; height: 26px; display: block; }
.mat-head { min-height: 34px; }
.mat-head h3 {
  font-size: 0.92rem;
  color: var(--paper);
  letter-spacing: 0.01em;
  line-height: 1.25;
}
.mat-head h3 em { font-style: normal; color: var(--orange); }
.mat:hover .mat-head h3 em { color: var(--yellow); }

.mat-desc {
  color: var(--paper-dim);
  font-size: 0.87rem;
  line-height: 1.62;
  flex: 1;
  margin-bottom: 14px;
}
.mat-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 11px;
  border-top: 1px solid var(--line);
}
/* Belt and braces after the meta text collided with the score: the label
   truncates rather than wrapping, and the score never shrinks. A long meta
   string should degrade, not overlap. */
.mat-meta {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.63rem;
  letter-spacing: 0.06em;
  color: var(--paper-mute);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.mat-go, .mat-score {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.66rem;
  color: var(--orange);
  flex-shrink: 0;
  white-space: nowrap;
}
.mat:hover .mat-go { color: var(--yellow); }
/* Been here before — show the score instead of the invitation. */
.mat-score { color: var(--yellow); }

/* ---------- how it works ---------- */
.how { margin: 34px 0 8px; }
.how h2 { font-size: 1.15rem; margin-bottom: 16px; }
.how-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.how-card {
  background: var(--graphite-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--yellow);
  padding: 16px 18px;
}
.how-card h3 { font-size: 0.88rem; margin-bottom: 7px; color: var(--paper); }
.how-card p { color: var(--paper-dim); font-size: 0.85rem; line-height: 1.62; }
