/* The PCIe chapters' benches: switches, a setpci console, lspci output. */
.pcie-switches { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0; }
.pcie-switch {
  min-height: 44px;
  padding: 0.55rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.pcie-switch::before { content: "− "; color: var(--deny); font-weight: 700; }
.pcie-switch[aria-pressed="true"] { border-color: var(--allow); }
.pcie-switch[aria-pressed="true"]::before { content: "+ "; color: var(--allow); }
.pcie-out {
  margin: 0.6rem 0;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--bg);
  font-family: var(--term-font);
  font-variant-ligatures: none;
  font-size: 0.9rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  tab-size: 4;
}
.pcie-out .is-new { color: var(--accent); font-weight: 700; }
.pcie-log { max-height: 12rem; overflow: auto; list-style: none; padding-left: 0; }
.pcie-log li { display: grid; gap: 0.1rem; margin-bottom: 0.35rem; }
.pcie-log code, .pcie-log samp { overflow-wrap: anywhere; }
.pcie-log .is-error { color: var(--deny); }
.pcie-console { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: end; }
.pcie-console label { flex: 1 1 18rem; display: grid; gap: 0.25rem; }
.pcie-console input { min-height: 44px; font-family: var(--term-font); font-variant-ligatures: none; width: 100%; box-sizing: border-box; }
.pcie-requests { list-style: none; padding-left: 0; }
.pcie-requests li { display: grid; margin: 0.35rem 0; padding-left: 0.6rem; border-left: 4px solid var(--deny); }
.pcie-requests li.is-ok { border-left-color: var(--allow); }
.pcie-requests span { color: var(--muted); }
.pcie-lanes { display: flex; flex-wrap: wrap; gap: 4px; margin: 0.6rem 0; }
.pcie-lanes span { width: 14px; height: 32px; border-radius: 3px; border: 1px solid var(--line); }
.pcie-lanes span.is-on { background: var(--accent); border-color: var(--accent); }
.pcie-annotated button {
  padding: 0.1rem 0.25rem;
  border: 1px dashed var(--muted);
  border-radius: 0.3rem;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.pcie-annotated button[aria-pressed="true"] { border-style: solid; border-color: var(--accent); background: var(--soft); }
.pcie-annotated { line-height: 2.4; }
.pcie-figure svg { width: 100%; height: auto; }
.pcie-figure text { fill: var(--ink); font: 14px sans-serif; }
.pcie-figure .muted { fill: var(--muted); font-size: 12px; }
.pcie-figure rect { fill: var(--surface); stroke: var(--line); stroke-width: 2; }
.pcie-figure .hot { stroke: var(--accent); }
.pcie-figure path { fill: none; stroke: var(--muted); stroke-width: 2; }
.pcie-figure .lane { stroke: var(--accent); }
/* Each diagram is drawn at least at its viewBox width (the scope, whose labels are 28px, at 12/28 of it),
   so no label renders under 12px; a phone scrolls it sideways (the figure is a tab stop for that). */
.pcie-map { max-width: 640px; }
.pcie-map svg { min-width: 480px; }
.pcie-figure, .phy-scope { margin-inline: 0; overflow-x: auto; }
.pcie-figure svg { min-width: 640px; }
.pcie-figure svg[viewBox^="0 0 760"] { min-width: 760px; }
.phy-scope svg { min-width: 494px; }
/* The capability lists as linked boxes. */
.pcie-chain { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 1.4rem; list-style: none; padding: 0; margin: 0.8rem 0; }
.pcie-chain li { position: relative; display: grid; padding: 0.35rem 0.6rem; border: 2px solid var(--line); border-radius: 0.5rem; background: var(--surface); }
.pcie-chain li:not(:last-child)::after { content: "→"; position: absolute; right: -1.15rem; top: 50%; transform: translateY(-50%); color: var(--muted); }
.pcie-chain b { font-family: monospace; }
.pcie-chain span { font-size: 0.85rem; color: var(--muted); }
.pcie-chain .is-on { border-color: var(--accent); }
.pcie-chain .is-now { border-color: var(--accent); background: var(--soft); }
.pcie-chain .pcie-chain-end { border-style: dashed; color: var(--muted); font-size: 0.85rem; }
/* lspci -vvv, one register per line group, each opening its note. */
.pcie-console textarea { font-family: var(--term-font); font-variant-ligatures: none; font-size: 0.85rem; width: 100%; box-sizing: border-box; }
.pcie-vvv { list-style: none; padding: 0; margin: 0.6rem 0; border: 1px solid var(--line); border-radius: 0.5rem; background: var(--bg); }
.pcie-vvv li + li { border-top: 1px solid var(--line); }
.pcie-vvv summary { padding: 0.3rem 0.6rem; cursor: pointer; }
.pcie-vvv summary code { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.85rem; }
.pcie-vvv details[open] summary { background: var(--soft); }
.pcie-vvv details > :not(summary) { margin: 0.4rem 0.8rem; }
.pcie-flags { padding-left: 0; list-style: none; }
.pcie-flags li { padding-left: 0.5rem; border-left: 4px solid var(--line); margin: 0.2rem 0; }
.pcie-flags li.is-on { border-left-color: var(--allow); }
.pcie-chain .is-no { border-color: var(--deny); }
.pcie-atomic-form label { flex: 1 1 9rem; }
.pcie-atomic-form select { min-height: 44px; }
.pcie-atomic-form [hidden] { display: none; }
.note-article :is(p, li, dt, dd) code, .pcie-vvv li { overflow-wrap: anywhere; }
.pcie-out .is-new::before { content: "» "; }
.pcie-flags li.is-no { border-left-color: var(--deny); }
/* Enumeration: the bus walk's tree, the ECAM fields, the pulse down the tree. */
.enum-tree ul { list-style: none; margin: 0; padding-left: 1.1rem; border-left: 2px solid var(--line); }
.enum-tree li { margin: 0.25rem 0; }
.enum-node { display: inline-block; padding: 0.15rem 0.45rem; border: 2px solid var(--line); border-radius: 0.4rem; color: var(--muted); }
.enum-node.is-on { border-color: var(--accent); color: var(--ink); }
.enum-node.is-now { border-color: var(--accent); background: var(--soft); color: var(--ink); }
.enum-node small { color: var(--muted); }
.enum-range { font-family: monospace; color: var(--accent); }
.enum-log li.is-write code { color: var(--accent); }
.enum-ecam label { flex: 1 1 6rem; }
.enum-ecam .pcie-out, .enum-fields { flex-basis: 100%; }
.enum-fields { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; padding: 0; }
.enum-fields li { display: grid; padding: 0.3rem 0.6rem; border: 1px solid var(--line); border-radius: 0.4rem; }
.enum-fields code { overflow-wrap: anywhere; }
.enum-fields span { color: var(--muted); font-size: 0.85rem; }
.enum-flow li { margin: 0.4rem 0; }
.pcie-figure .enum-empty, .viommu-map .enum-empty { stroke-dasharray: 6 4; }
.pcie-figure .enum-pulse { fill: var(--accent); stroke: none; }
html[data-motion=on] .enum-pulse { cx: 0; cy: 0; offset-path: path("M320 52V192H470"); offset-rotate: 0deg; animation: enum-pulse 4s linear infinite; }
@keyframes enum-pulse { to { offset-distance: 100%; } }
/* Physical layer: bits along the lanes, the scope, the eyes, the flit. */
.pcie-figure .phy-bit { fill: var(--accent); stroke: none; }
html[data-motion=on] .phy-bit { animation: phy-out 3s linear infinite; }
html[data-motion=on] .phy-bit.phy-late { animation-delay: -1.5s; }
html[data-motion=on] .phy-bit.phy-back { animation-name: phy-back; }
@keyframes phy-out { to { transform: translateX(340px); } }
@keyframes phy-back { to { transform: translateX(-340px); } }
.phy-scope-form label { flex: 1 1 12rem; }
.phy-scope svg { width: 100%; height: auto; }
.phy-scope .scope-label { fill: var(--ink); font: 28px sans-serif; }
.phy-scope .scope-threshold { stroke: var(--muted); stroke-width: 2; stroke-dasharray: 8 8; }
.phy-scope .scope-line { fill: none; stroke: var(--accent); stroke-width: 4; stroke-dasharray: 6000; }
.phy-scope .scope-ok { fill: var(--allow); }
.phy-scope .scope-bad { fill: var(--deny); stroke: var(--ink); stroke-width: 2; }
.phy-eyes { display: flex; flex-wrap: wrap; gap: 1rem; }
.phy-eyes figure { flex: 1 1 10rem; max-width: 16rem; margin: 0; }
.phy-eyes svg { width: 100%; height: auto; background: var(--bg); border: 1px solid var(--line); border-radius: 0.4rem; }
.phy-eyes .scope-trace { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0.35; }
/* 16 tracks of 44px (the touch-target size), so a row scrolls sideways in its own region on a narrow screen. */
.phy-flit-grid { display: grid; grid-template-columns: repeat(16, 44px); gap: 2px; overflow-x: auto; padding-bottom: 4px; }
/* Above the grid, so it stays in view; two lines reserved, so a changing readout never moves the bytes under a tap. */
.phy-flit-byte { margin: 0.4rem 0; min-height: 3em; line-height: 1.5; font-family: monospace; }
.phy-flit-grid button { min-height: 44px; min-width: 0; padding: 0; border: 1px solid var(--line); border-radius: 2px; cursor: pointer; font: 700 0.75rem sans-serif; color: var(--bg); }
.phy-flit-grid button[aria-pressed="true"] { --flit: var(--deny); }
.phy-flit-grid button[aria-pressed="true"]::after { content: "×"; }
.flit-tlp { --flit: var(--surface); }
.flit-dlp { --flit: color-mix(in srgb, var(--second) 45%, var(--surface)); }
.flit-crc { --flit: color-mix(in srgb, var(--allow) 45%, var(--surface)); }
.flit-fec { --flit: color-mix(in srgb, var(--accent) 45%, var(--surface)); }
.phy-flit-grid button { background: var(--flit); }
.phy-flit-legend { display: grid; gap: 0.3rem; list-style: none; padding: 0; }
.phy-flit-legend li { display: grid; grid-template-columns: 1.2rem 1fr; column-gap: 0.5rem; }
.phy-flit-legend li::before { content: ""; grid-row: span 2; width: 1.2rem; height: 1.2rem; border: 1px solid var(--line); border-radius: 2px; background: var(--flit); }
.phy-flit-legend span { color: var(--muted); font-size: 0.9rem; }
.phy-groups li { display: grid; }
/* CXL: a load crossing to the card, the device picker, flits, the interleave strip. */
.pcie-figure .cxl-load { fill: var(--accent); stroke: none; }
html[data-motion=on] .cxl-load { animation: cxl-load 3s ease-in-out infinite alternate; }
@keyframes cxl-load { to { transform: translateX(240px); } }
.cxl-picker fieldset { flex: 1 1 18rem; display: grid; gap: 0.3rem; border: 1px solid var(--line); border-radius: 0.5rem; }
.cxl-picker label, .cxl-host { display: flex; gap: 0.5rem; align-items: center; min-height: 44px; }
.cxl-picker input { width: auto; min-height: 0; }
.cxl-stream, .cxl-strip { display: flex; flex-wrap: wrap; gap: 0.3rem; list-style: none; padding: 0; margin: 0.6rem 0; }
.cxl-stream li, .cxl-strip li { display: grid; padding: 0.25rem 0.5rem; border: 2px solid var(--line); border-radius: 0.4rem; font-size: 0.85rem; }
.cxl-stream span, .cxl-strip span { color: var(--muted); font-family: monospace; }
.cxl-cachemem, .cxl-dev-1 { border-color: var(--accent); }
.cxl-io, .cxl-dev-2 { border-color: var(--second); }
.cxl-null { border-style: dashed; }
.cxl-dev-3 { border-color: var(--allow); }
.cxl-strip li.is-now { background: var(--soft); outline: 3px solid var(--accent); }
.cxl-calc label { flex: 1 1 9rem; }
.cxl-calc select { min-height: 44px; }
.cxl-calc output { flex-basis: 100%; white-space: normal; }
.cxl-timeline { list-style: none; padding-left: 0; border-left: 3px solid var(--line); }
.cxl-timeline li { display: grid; margin: 0 0 0.6rem; padding-left: 0.8rem; }
.cxl-timeline span { color: var(--muted); }
.pcie-out.pcie-wide { white-space: pre; overflow-wrap: normal; width: max-content; }
.pcie-annotated button { overflow-wrap: anywhere; }
/* PCIe chapters: a panel's h3 ranks below its h2, and running text keeps a measure (figures and labs stay wide). */
.lesson-panel h3 { font-size: 1.2rem; line-height: 1.35; letter-spacing: -0.02em; margin: 1.6rem 0 0.5rem; }
.lesson-panel > :is(p, ul, ol):not([class]) { max-width: 75ch; }
/* PcieLab's root: the output grid, compact panel headings and action row that .shared-page gives the IOMMU labs (this root is .edge-page, not .shared-page). */
.pcie-lab-root h3 { margin: 1rem 0 0.5rem; font-size: 1rem; line-height: 1.35; }
.pcie-lab-root .shared-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-block: 1rem; }
.pcie-lab-root .shared-memory { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: 1rem; margin: 1.3rem 0; }
.pcie-lab-root .shared-memory > .shared-node { min-width: 0; padding: 0.9rem 1rem; border: 1px solid var(--line); border-radius: 14px; background: var(--bg); }
.pcie-lab-root .shared-memory h3 { margin-top: 0; }
/* Diagrams: the flit's parts and an lspci line (box and text styles come from iommu/viommu.css). */
/* At least 800px wide (scrolling sideways in the figure on a phone), with no label under 15px,
   so no label renders under 12px. */
.phy-flit-fig, .lspci-fig { max-width: none; }
.phy-flit-fig svg, .lspci-fig svg { min-width: 800px; }
.phy-flit-fig .viommu-small, .lspci-fig .viommu-small { font-size: 15px; }
.phy-flit-fig [data-flit-part] rect { fill: var(--flit); stroke: var(--line); stroke-width: 1.5; }
.phy-fg0 rect { stroke: var(--accent); }
.phy-fg1 rect { stroke: var(--second); }
.phy-fg2 rect { stroke: var(--allow); }
.phy-flit-groups rect { fill: var(--surface); stroke-width: 3; }
.lspci-fig [data-lspci-part] > rect { fill: var(--surface); stroke: var(--line); stroke-width: 1.5; }
.lspci-fig text { font-family: ui-monospace, Consolas, monospace; }
.lspci-fig .viommu-small { font-family: system-ui, sans-serif; }
.lspci-fig .lspci-term { fill: var(--accent); font: 600 15px/1 system-ui, sans-serif; }
.lspci-brace { fill: none; stroke: var(--muted); stroke-width: 2; }
