/* SynapticSci draft site — spine.css (2026-09-05).
   The complete-page spine for lab and product pages: summary60, the anchor rail, the nine
   fixed sections, placeholder plates, the then/now <picture> device, SVG figure wrapper and
   tokens, toggle/phrase margin marks, and the procurement aside.
   Extends site.css (journal plates, hairlines, matte figures, STIX display); never redefines
   its tokens. Load order (head partial): fonts.css → site.css → spine.css → review.css.
   review.css also styles .plate (draft chrome, 2026-09-02); the rules here are written at
   `main .plate` so they win regardless of that order. Markup contract: _build/COMPONENTS.md. */

/* ---- tokens added by the spine ---- */
:root{
  /* figure colours: inline SVG uses these by name (fill="var(--fig-primary)") or via the
     .f-* utility classes below, so a token change recolours every figure at once */
  --fig-ink:var(--ink); --fig-ink-soft:var(--ink-soft); --fig-soft:var(--ink-soft); --fig-primary:var(--primary);
  --fig-primary-deep:var(--primary-deep); --fig-patina:var(--patina); --fig-patina-deep:var(--patina-deep);
  --fig-withheld:var(--status-withheld); --fig-held:var(--held-bg); --fig-paper:var(--paper); --fig-surface:var(--surface);
  --fig-rule:var(--rule); --fig-pen:var(--pen);
  --fig-sheet:var(--surface); --fig-sheet-edge:var(--rule); --fig-sheet-rule:var(--rule);
  /* the dendrite's two stroke tones: the DS keeps these as an accepted exception (DS .design-sync/NOTES.md,
     dendrite-live.js); declared once here so every figure reads them by name */
  --fig-dendrite:#c9c0ab; --fig-dendrite-soft:#ddd5c2; --fig-dendrite-fine:#ddd5c2;
  /* layout */
  --rail-w:200px; --spine-gap:48px; --spine-max:1320px; --spine-pad:48px;
  --sticky-top:24px;            /* the chrome agent may raise this if the masthead becomes sticky */
  --rail-strip-h:46px;          /* height of the horizontal rail strip on narrow screens */
}
/* dark mode (ds/mode-dark.css; screen only, same two selectors the DS uses): the dendrite's paper-toned strokes
   would glow on the dark ground, so they sit between the dark hairline and the dark control border instead */
@media screen and (prefers-color-scheme:dark){
  :root:not([data-mode="light"]){
    --fig-dendrite:color-mix(in srgb,var(--border-control) 35%,var(--rule));
    --fig-dendrite-soft:color-mix(in srgb,var(--border-control) 15%,var(--rule)); --fig-dendrite-fine:var(--fig-dendrite-soft);
  }
}
@media screen{
  [data-mode="dark"]{
    --fig-dendrite:color-mix(in srgb,var(--border-control) 35%,var(--rule));
    --fig-dendrite-soft:color-mix(in srgb,var(--border-control) 15%,var(--rule)); --fig-dendrite-fine:var(--fig-dendrite-soft);
  }
}
/* the live dendrite (dendrite-live.js) writes its stroke tones as attributes; read them from the tokens so the mode applies */
[data-dendrite] svg > g > path:first-child{stroke:var(--fig-dendrite)}
[data-dendrite] svg > g > path:not(:first-child){stroke:var(--fig-dendrite-soft)}

/* ---- page head: eyebrow · H1 · summary60 · brand-line lede ---- */
.spine-head{max-width:var(--spine-max);margin:0 auto;padding:56px var(--spine-pad) 8px}
.spine-head .sect{margin:0 0 14px}
.spine-head h1{font-size:clamp(34px,3.4vw,54px);line-height:1.08;max-width:22ch;margin:0 0 20px}
.spine-head h1 .h1-for{display:block;font-weight:400;font-style:italic;font-size:.62em;line-height:1.25;color:var(--ink-soft);margin-top:6px}
.spine-head .lede{font-family:var(--font-display);font-style:italic;font-size:clamp(20px,1.7vw,25px);line-height:1.3;color:var(--primary-deep);max-width:34ch;margin:18px 0 0}

/* the sixty-word plain summary: first under the H1; also the meta description and the
   JSON-LD description, verbatim. Body face, no display styling — it is prose, not a slogan. */
.summary60{font-family:var(--font-body);font-size:18px;line-height:1.6;color:var(--ink);max-width:62ch;margin:0;padding:14px 0 16px;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.summary60 b,.summary60 strong{font-weight:600}

/* ---- the two-column layout: rail + spine ---- */
.spine-layout{max-width:var(--spine-max);margin:0 auto;padding:0 var(--spine-pad) 40px}
.spine{min-width:0}
.spine-sec{padding:44px 0 40px;border-top:1px solid var(--rule);scroll-margin-top:calc(var(--sticky-top) + 8px)}
.spine-sec:first-child{border-top:0;padding-top:28px}
.spine-sec .sect{margin:0 0 10px}
.spine-sec .sect .n{color:var(--ink-soft);letter-spacing:.06em;margin-right:8px}
.spine-sec h2{font-size:30px;margin:0 0 16px;max-width:26ch}
.spine-sec h3{font-size:20px;margin:24px 0 8px}
.spine-sec p,.spine-sec li{max-width:68ch}
.spine-sec p{margin:0 0 14px}
.spine-sec p:last-child{margin-bottom:0}
.spine-sec .fig,.spine-sec .plate,.spine-sec .roles,.spine-sec .procure,.spine-sec .offer-grid,.spine-sec .proof-grid,.spine-sec .bounds{margin-top:28px}
.spine-sec .offer-grid{text-align:left}
.spine-sec .ev{margin:18px 0 0}
.spine-sec .decision{margin-left:0;margin-right:0}
.spine-sec .held-note{margin-top:20px}
.spine [id]{scroll-margin-top:calc(var(--sticky-top) + 8px)}

/* the "not for" line in #who: the boundary, high on the page, pointing at #boundaries */
.notfor{font-size:14.5px;color:var(--ink-soft);border-left:2px solid var(--status-withheld);padding:6px 0 6px 14px;margin:18px 0 0;max-width:62ch}
.notfor b{color:var(--status-withheld);font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;margin-right:6px}

/* persona subsections inside #how — anchors #leadership #bench #qa #it, never nav */
.roles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(360px,100%),1fr));gap:22px 28px}  /* 2×2 in the 976px column, one column on phones */
.role{border-top:2px solid var(--ink);padding-top:12px;min-width:0}
.role .rolek{font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--patina-deep);margin:0 0 6px}
.role h3{font-size:19px;margin:0 0 8px}
.role p{font-size:14.5px;margin:0 0 10px;max-width:none}
.role li{font-size:14.5px}  /* the bullets match the role's paragraphs (review pins 0mulosuyewxhusm, 0mulot0cqhxvuhh, 0mulot30oiq8cd9, 0mulot5jsav43sl) */
.role p:last-child{margin-bottom:0}

/* operating boundaries list (#boundaries) */
.bounds{list-style:none;margin:0;padding:0;border-top:1px solid var(--rule)}
.bounds li{position:relative;padding:12px 0 12px 20px;border-bottom:1px solid var(--rule);font-size:15px}
.bounds li::before{content:"";position:absolute;left:0;top:22px;width:9px;height:2px;background:var(--status-withheld)}

/* proof card rows (plan §2.7): Claim → Mechanism → Visible artifact → Operating boundary → Attributed result */
.proof-card p:has(> .pk){position:relative;padding-left:9.5em}
.proof-card .pk{position:absolute;left:0;top:.35em;font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--patina-deep);font-weight:700}
@media (max-width:520px){.proof-card p:has(> .pk){padding-left:0;padding-top:1.4em}}
.proof-card .grade{font-family:var(--font-mono);font-size:12px;color:var(--ink-soft)}
a.grade,.proof-card a.grade{color:var(--primary);text-decoration:underline;text-underline-offset:2px}
a.grade:hover,a.grade:focus-visible,.proof-card a.grade:hover,.proof-card a.grade:focus-visible{color:var(--primary-deep);text-decoration-thickness:2px}
/* the anonymity sentence under every proof card */
.anon{font-family:var(--font-display);font-style:italic;font-size:14.5px;color:var(--ink-soft);margin-top:16px}

/* ---- team sections (story 36-4): rendered from data.people into [data-team]; shared by the hubs and /our-science/ ---- */
.team-grid{list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(min(170px,100%),1fr));gap:20px;margin:28px 0 0;padding:0}
/* night run 2026-10-09: each member is a card on the sheet (one portrait crop, name, role, practice tags); the whole
   card is the link to their page (the name's link stretched over it), so the grid reads as a team, not a list */
.team-grid > li.person{position:relative;display:flex;flex-direction:column;margin:0;padding:10px 10px 14px;border:1px solid var(--rule);border-top:3px solid var(--ink);background:var(--surface);max-width:none;transition:border-color var(--motion-fast)}
.team-grid > li.person:hover,.team-grid > li.person:focus-within{border-color:var(--primary);border-top-color:var(--primary)}
.team-grid .pphoto,.team-grid .pmono{display:block;box-sizing:border-box;width:100%;max-width:none;height:auto;aspect-ratio:1/1;object-fit:cover;border:1px solid var(--rule);margin:0 0 12px;background:var(--paper)}
.team-grid picture{display:block}
.team-grid .pmono{display:grid;place-items:center;font-family:var(--font-display);font-size:clamp(28px,3.4vw,40px);letter-spacing:.06em;color:var(--ink-soft);background-color:var(--paper);background-image:linear-gradient(color-mix(in srgb,var(--primary) 9%,transparent) 1px,transparent 1px),linear-gradient(90deg,color-mix(in srgb,var(--primary) 9%,transparent) 1px,transparent 1px);background-size:16px 16px}
.team-grid .who{font-family:var(--font-display);font-size:19px;line-height:1.25;margin:0 0 4px}
.team-grid .who a{text-decoration-thickness:1px}
.team-grid > li.person .who a::after{content:"";position:absolute;inset:0}
.team-grid .prole{font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--patina-deep);margin:0}
.team-grid .pline{font-size:14.5px;line-height:1.55;color:var(--ink-soft);margin:8px 0 0;max-width:none}
.team-grid .ptags{--fig-pt-hue:var(--primary);list-style:none;display:flex;flex-direction:column;gap:5px;margin:10px 0 0;padding:0}
.team-grid .ptags li{margin:0;padding:0 0 0 8px;border-left:3px solid var(--fig-pt-hue);font-family:var(--font-label);font-size:12px;line-height:1.35;letter-spacing:.02em;color:var(--ink-soft);max-width:none}
/* the member whose record carries a line: a wide card (two columns, the whole row on a phone), the portrait beside the words */
.team-grid > li.person-wide{grid-column:span 2;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);grid-template-rows:auto auto auto 1fr;column-gap:18px;align-content:start}
.team-grid > li.person-wide > :is(picture,.pphoto,.pmono){grid-column:1;grid-row:1 / span 5;margin:0}
.team-grid > li.person-wide > :not(picture):not(.pphoto):not(.pmono){grid-column:2}
@media (max-width:600px){.team-grid{grid-template-columns:repeat(auto-fill,minmax(min(150px,100%),1fr));gap:14px}.team-grid > li.person{padding:8px 8px 12px}.team-grid .who{font-size:17px}.team-grid .prole{font-size:12px;letter-spacing:.06em}}

/* skip link: first element in <body>, before the nav partial */
.skip{position:absolute;left:-9999px;top:8px;z-index:100;background:var(--ground-ink);color:var(--on-ink-text);padding:8px 14px;font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;text-decoration:none}
.skip:focus{left:8px}

/* ---- the rail: sticky column ≥1100px, horizontal strip below ---- */
/* rail: DS .ss-rail (.rail stays as the hook for rail-progress.js); site keeps layout, numbering and progress */
.rail-in{display:block}
.rail ul + .rail-h{margin-top:22px}
.rail a{transition:color .2s,border-color .2s}
.rail a .rn{font-family:var(--font-mono);font-size:12px;color:var(--ink-soft);margin-right:6px;letter-spacing:.04em}
.rail a[aria-current] .rn{color:var(--patina-deep)}

/* ---- figure hero (D115 A1; operator, 2026-09-24): the home page's layout on every page that has a
   then/now figure. The head text beside the figure on a desktop, the figure first on a phone. The head
   drops the rail indent so the figure has the room it has on the home page. */
.spine-head.hero-fig{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:center}
.spine-head.hero-fig .hero-text{min-width:0}
/* L5.3: on a phone the H1 and the action come first, the figure follows (it was first and pushed the H1 below the fold) */
.spine-head.hero-fig .hero-media{order:0;margin:0;min-width:0}
/* the device inside is the DS ThenNow (.tn-mount > .ss-thennow > .tn-frame); the DS sizes both images, so this
   head sets only the mount's spacing and leaves the NOW image's cover fit to ds/components.css */
.spine-head.hero-fig .hero-media .tn-mount{margin:0 0 8px}
.spine-head.hero-fig .hero-media .tn-then img{display:block;width:100%;height:auto}
.spine-head.hero-fig .hero-media .figcap{line-height:1.5}
@media (min-width:760px){
  .spine-head.hero-fig{grid-template-columns:minmax(0,1fr) minmax(0,1.08fr);gap:24px 54px;padding-bottom:40px}
  .spine-head.hero-fig .hero-media{order:0;justify-self:center;width:min(100%,calc(72vh * var(--fig-ar,1.5)))}
}

@media (min-width:1100px){
  .spine-layout{display:grid;grid-template-columns:var(--rail-w) minmax(0,1fr);column-gap:var(--spine-gap);align-items:start}
  .spine-head{padding-left:calc(var(--spine-pad) + var(--rail-w) + var(--spine-gap))}
  .spine-head.hero-fig{padding-left:var(--spine-pad)}
  /* the rail offset is only for pages that HAVE a rail: a page without one (person pages, Lab Notes) got a
     phantom 324px left gutter that squeezed its header to a 280px strip (Doug, 2026-10-09) */
  main:not(:has(.rail)) > .spine-head:not(.hero-fig){padding-left:var(--spine-pad)}
  .rail{position:sticky;top:var(--sticky-top);max-height:calc(100vh - var(--sticky-top) - 16px);overflow:auto;padding:28px 0 16px;scrollbar-width:thin}
}
@media (min-width:1500px){
  :root{--spine-max:1500px;--rail-w:220px;--spine-gap:56px}   /* matches site.css's .wide at ≥1500px */
  .spine-sec p,.spine-sec li{max-width:70ch}
}
@media (max-width:1099px){
  .spine-head{padding-top:40px}
  .rail{position:sticky;top:0;z-index:6;background:var(--paper);border-bottom:1px solid var(--rule);margin:0 calc(-1 * var(--spine-pad));padding:0 var(--spine-pad)}
  .rail-in{display:flex;flex-direction:row;align-items:center;gap:0;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .rail-in::-webkit-scrollbar{display:none}
  .rail-h{padding:0 10px 0 0;margin:0;white-space:nowrap;flex:0 0 auto}
  .rail ul + .rail-h{margin:0 0 0 18px;padding-left:18px;border-left:1px solid var(--rule)}
  .rail ul{display:flex;flex:0 0 auto}
  .rail li{flex:0 0 auto}
  .rail a{border-left:0;padding:13px 9px;white-space:nowrap;border-bottom:2px solid transparent;height:var(--rail-strip-h);box-sizing:border-box}
  .rail a[aria-current]{border-left:0;padding-left:9px;border-bottom-color:var(--patina-deep)}
  .spine-sec,.spine [id]{scroll-margin-top:calc(var(--rail-strip-h) + 8px)}
}
@media (max-width:900px){
  :root{--spine-pad:24px}
  .spine-head{padding-top:32px}
  .spine-head h1{font-size:clamp(30px,8vw,40px)}
  .summary60{font-size:17px}
  .spine-sec{padding:32px 0 30px}
  .spine-sec h2{font-size:26px}
}

/* ---- placeholder plates (plan §7.0): slot · description · PLACEHOLDER · asset round ----
   Matte look with no extra element: a dashed inner border plus a solid outer frame drawn by
   box-shadow, so the plates already on the draft (figure.plate > .pl-tag + .pl-desc) take the
   look without markup changes. `main .plate` outranks review.css's .plate on purpose. */
main .plate{position:relative;margin:9px;padding:36px 28px;text-align:center;background:var(--status-review-bg);border:1px dashed var(--ink-soft);box-shadow:0 0 0 8px var(--surface),0 0 0 9px var(--ink);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:180px}
main .plate .pl-slot{font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--primary-deep);margin:0}
main .plate .pl-desc{font-size:14.5px;line-height:1.5;color:var(--ink-soft);max-width:52ch;margin:0}
main .plate .pl-tag{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--status-withheld);font-weight:700;margin:0}
main .plate .pl-sub{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--status-withheld);margin:6px 0 0}
main .plate--photo{aspect-ratio:3/2;min-height:220px}
main .plate--photo::before{content:"";position:absolute;inset:14px;border:1px solid var(--rule);pointer-events:none}
main .plate--screenshot{padding:28px 24px 30px;background:var(--surface)}
main .plate--screenshot .record{width:100%;max-width:560px;margin:14px auto 0;text-align:left}
main .plate--screenshot .rec-row{opacity:1;transform:none}
main .plate--screenshot .rec-foot{opacity:1}
main .plate--now{background:var(--primary-wash);border-color:var(--primary)}
main .plate--now .pl-tag{color:var(--primary-deep)}
main .plate--now .pl-sub{color:var(--status-withheld)}
/* a figure that is only a plate sits inside .fig like any other figure; the caption follows */
.fig > .plate{margin:9px 9px 0}

/* ---- then/now device, extended (site.css defines the hover) ----
   "then" is a <picture class="then"> (WebP + JPEG, 1600/1000/600, sizes); "now" is a real
   image, a .plate--now, or the record-panel device. The device sits inside .matte, inside .fig. */
.tn{display:block}
.tn picture.then{display:block;width:100%}
.tn picture.then img{display:block;width:100%;height:auto}
.tn .now .plate--now{position:absolute;inset:0;margin:0;box-shadow:none;border:0;min-height:0;padding:28px 24px;background:var(--primary-wash)}
.tn .now .now-record{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--primary-wash);text-align:left}
.tn .now .now-record .record{width:100%;max-width:440px;box-shadow:var(--elevation-paper)}
.tn .now .now-record .rec-row{opacity:1;transform:none}
.tn .now .now-record .rec-foot{opacity:1}
.tn:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}
@media (hover:none){.tn .hint{opacity:.85}}

/* ---- figures: .fig wraps an inline SVG (or a plate, or a matte photo) with a numbered .figcap ---- */
.fig{margin:0;min-width:0}
.fig > svg,.fig .matte > svg{display:block;width:100%;height:auto}
.fig .matte{margin:0}
.fig .figcap{margin-top:10px;font-size:12.5px;line-height:1.5;color:var(--ink-soft)}
.fig .figcap .fign{font-family:var(--font-mono);color:var(--patina-deep);letter-spacing:.1em;text-transform:uppercase;font-size:12px;margin-right:6px}
.figcap .cred{display:block;margin-top:3px;font-family:var(--font-mono);font-size:12px;letter-spacing:.03em;color:var(--ink-soft)}

/* ---- phone drawings of the site's own figures (2026-10-08) ----
   A labelled figure carries two drawings with the same words: the desktop drawing (svg[data-fig-copy="desktop"]) and a
   phone drawing (svg[data-fig-copy="phone"], 300 units wide) whose labels are 13.5 units or more, so they read at 12px
   or more on a 360-390px phone. Exactly one of the two shows at any width, so a screen reader meets one title and one
   description; print always takes the desktop drawing. src/domain/figure-phone-copy.test.ts proves the phone drawing's
   words equal the desktop drawing's, word for word, and holds the phone label sizes to the floor. */
@media screen and (max-width:759.98px){svg[data-fig-copy="desktop"]{display:none!important}}
@media print,screen and (min-width:760px){svg[data-fig-copy="phone"]{display:none!important}}
.fig .matte > svg.fig-phone,svg.fig-phone{display:block;width:100%;height:auto;max-width:440px;margin:0 auto;font-kerning:normal}
.fig-phone .fp-num{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.08em;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-name{font-family:var(--font-display);font-weight:600;font-size:21px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-name-s{font-family:var(--font-display);font-weight:600;font-size:18px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-sci{font-family:var(--font-display);font-style:italic;font-size:16px;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-it{font-family:var(--font-display);font-style:italic;font-size:16px;fill:var(--fig-ink-soft,#6e675c)}
.fig-phone .fp-gate{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.05em;fill:var(--fig-ink-soft,#6e675c)}
.fig-phone .fp-caps{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.1em;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-body{font-family:var(--font-body);font-size:15px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-soft{font-family:var(--font-body);font-size:14px;fill:var(--fig-ink-soft,#6e675c)}
.fig-phone .fp-strong{font-family:var(--font-body);font-weight:600;font-size:16px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-q{font-family:var(--font-display);font-weight:600;font-size:19px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-charge{font-family:var(--font-display);font-size:19px;fill:var(--fig-ink,#221f1a)}
.fig-phone .fp-key{font-family:var(--font-mono);font-weight:700;font-size:14px;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-lbl{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.05em;fill:var(--fig-ink-soft,#6e675c)}
.fig-phone .fp-conf{font-family:var(--font-mono);font-weight:700;font-size:15px;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-hand{font-family:var(--font-hand);font-size:30px;fill:var(--fig-pen,#2b3a8c)}
.fig-phone .fp-stamp{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.14em;fill:var(--fig-patina-deep,#0e6b5e)}
.fig-phone .fp-flag{font-family:var(--font-mono);font-size:13.5px;letter-spacing:.05em;fill:var(--fig-surface,#ffffff)}
.fig-phone .fp-held-text{fill:var(--fig-withheld,#9c1b34)}
.fig-phone .fp-ov{font-family:var(--font-mono);font-size:13.5px;fill:var(--fig-primary,#243e9c)}
.fig-phone .fp-track{fill:none;stroke:var(--fig-dendrite,#c9c0ab);stroke-width:1.6;stroke-linecap:round}
.fig-phone .fp-track-soft{fill:none;stroke:var(--fig-dendrite-soft,#ddd5c2);stroke-width:1;stroke-linecap:round}
.fig-phone .fp-track-held{fill:none;stroke:var(--fig-dendrite,#c9c0ab);stroke-width:1.6;stroke-dasharray:3 5;stroke-linecap:round}
.fig-phone .fp-soma{fill:var(--fig-primary,#243e9c)}
.fig-phone .fp-ring{fill:none;stroke:var(--fig-primary,#243e9c);stroke-width:1.2;opacity:.35}
.fig-phone .fp-ring-strong{fill:none;stroke:var(--fig-patina,#22a695);stroke-width:1.6}
.fig-phone .fp-receptor{fill:var(--fig-paper,#fcfaf4);stroke:var(--fig-primary,#243e9c);stroke-width:2}
.fig-phone .fp-core{fill:var(--fig-patina,#22a695)}
.fig-phone .fp-open{fill:var(--fig-surface,#ffffff);stroke:var(--fig-primary,#243e9c);stroke-width:1.6}
.fig-phone .fp-hollow{fill:var(--fig-paper,#fcfaf4);stroke:var(--fig-dendrite,#c9c0ab);stroke-width:1.4}
.fig-phone .fp-chev{fill:var(--fig-patina,#22a695)}
.fig-phone .fp-mark{fill:var(--fig-primary,#243e9c)}
.fig-phone .fp-badge{fill:var(--fig-paper,#fcfaf4);stroke:var(--fig-rule,#e4ded3);stroke-width:1}
.fig-phone .fp-rule{fill:none;stroke:var(--fig-rule,#e4ded3);stroke-width:1}
.fig-phone .fp-hair{fill:none;stroke:var(--fig-ink,#221f1a);stroke-width:1.2}
.fig-phone .fp-sheet{fill:var(--fig-sheet,#fffdf6);stroke:var(--fig-sheet-edge,#e7e0d0);stroke-width:1}
.fig-phone .fp-sheet-rule{fill:none;stroke:var(--fig-sheet-rule,#e9e2d2);stroke-width:1}
.fig-phone .fp-surface{fill:var(--fig-surface,#ffffff);stroke:var(--fig-rule,#e4ded3);stroke-width:1}
.fig-phone .fp-stamp-box{fill:none;stroke:var(--fig-patina,#22a695);stroke-width:1.6}
.fig-phone .fp-chip{fill:var(--fig-patina,#22a695);fill-opacity:.1}
.fig-phone .fp-chip-held{fill:var(--fig-withheld,#9c1b34);fill-opacity:.08}
.fig-phone .fp-flag-box{fill:var(--fig-withheld,#9c1b34)}
.fig-phone .fp-held-bg{fill:var(--fig-held,#f4f1ea)}
.fig-phone .fp-held-ring{fill:none;stroke:var(--fig-withheld,#9c1b34);stroke-width:1.8}
.fig-phone .fp-bar{fill:var(--fig-primary,#243e9c)}
.fig-phone .fp-tick{fill:none;stroke:var(--fig-rule,#e4ded3);stroke-width:1}
.fig-phone .fp-line-strong{fill:none;stroke:var(--fig-primary,#243e9c);stroke-width:2;stroke-linecap:round}
.fig-phone .fp-upper{text-transform:uppercase}
.fig-phone .fp-messy{letter-spacing:.06em}
.fig-phone .fp-letters{letter-spacing:.06em}
.fig-phone .fp-rec-head{fill:var(--fig-primary-deep,#182a6e)}
.fig-phone .fp-stamp-rot{transform-box:fill-box;transform-origin:center;transform:rotate(-6deg)}
@media (prefers-reduced-motion:reduce){.fig-phone .fp-impulse{display:none}}
/* ---- end of the phone drawings ---- */

.figcap .cred--now{color:var(--primary-deep)}
.figcap .cred--placeholder{color:var(--status-withheld)}

/* ---- price records (story 34-9): site-build fills each empty <span class="price" data-price-record>; a placeholder
   reads as a review mark and wraps inside a table cell ---- */
.price{overflow-wrap:anywhere}
.price .price-terms{color:var(--ink-soft)}
.price--placeholder .price-value{color:var(--status-withheld)}
.price--placeholder code.price-id{font-family:var(--font-mono);font-size:.82em;letter-spacing:.02em;color:var(--status-withheld);overflow-wrap:anywhere}
/* the price-list table (spec-salesops-price-list): its caption, the shared terms typed once above it, and each item's
   short unit, muted and small, on its own line under the item */
.price-list{margin:18px 0 22px}
.price-list .price-caption{margin:0;padding:6px 10px 0;max-width:none}
.price-list .price-shared{margin:6px 0 4px;padding:0 10px;font-size:13.5px;line-height:1.55;color:var(--ink-soft);max-width:none}
.price-table .price-unit{display:block;margin-top:2px;font-family:var(--font-body);font-size:12.5px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--ink-soft)}
.price-table .price-rules{color:var(--ink)}
.fig--full{margin-left:calc(-1 * var(--spine-pad));margin-right:calc(-1 * var(--spine-pad))}
@media (min-width:1100px){.fig--full{margin-left:0;margin-right:0}}
/* SVG utility classes — theme-token colours, so figures never carry hex values */
.fig .f-ink{fill:var(--fig-ink)} .fig .f-primary{fill:var(--fig-primary)} .fig .f-patina{fill:var(--fig-patina)}
.fig .f-withheld{fill:var(--fig-withheld)} .fig .f-paper{fill:var(--fig-paper)} .fig .f-soft{fill:var(--fig-soft)}
.fig .f-line{fill:none;stroke:var(--fig-ink);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.fig .f-line-primary{fill:none;stroke:var(--fig-primary);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.fig .f-line-patina{fill:none;stroke:var(--fig-patina);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.fig .f-line-rule{fill:none;stroke:var(--fig-rule);stroke-width:1}
.fig .f-line-withheld{fill:none;stroke:var(--fig-withheld);stroke-width:1.4;stroke-dasharray:4 3}
.fig .f-display{font-family:var(--font-display);font-weight:600;fill:var(--fig-ink)}
.fig .f-italic{font-family:var(--font-display);font-style:italic;fill:var(--fig-patina-deep)}
.fig .f-mono{font-family:var(--font-mono);fill:var(--fig-soft);letter-spacing:.08em;text-transform:uppercase}
.fig .f-body{font-family:var(--font-body);fill:var(--fig-ink)}
.fig .f-pulse{animation:figpulse 5s ease-in-out infinite}
@keyframes figpulse{0%,100%{opacity:.55}50%{opacity:1}}

/* ---- toggles and phrase slots ----
   The margin marks that print a slot's id ("P-2 · 22") are review machinery: they live in review/review.css, which the
   publish build never ships, and the publish filter strips data-toggle, data-variant and data-phrase from every page as
   well (persona-panel leak, 2026-10-05). Only the rule that hides an unpicked variant stays here. */
[data-toggle][hidden]{display:none!important}

/* ---- the procurement bundle: bucket · data terms · references · boundaries, with anchors ---- */
.procure{border-top:3px double var(--ink);border-bottom:1px solid var(--ink);padding:16px 0 14px;max-width:70ch;font-size:14.5px}
.procure .procure-h{font-family:var(--font-mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--patina-deep);margin:0 0 12px}
.procure dl{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:9px 22px;margin:0}
.procure dt{font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft);padding-top:3px}
.procure dd{margin:0;max-width:none}
.procure dd a{white-space:nowrap}
/* a dd that is one long link ("Designed to support your accreditation, which your laboratory holds") ran past the
   rule at 1440 and 2000: a lone link may wrap; links in a list stay whole (review 2026-10-09) */
.procure dd a:only-child{white-space:normal}
@media (max-width:520px){.procure dl{grid-template-columns:1fr;gap:4px}.procure dd{margin-bottom:8px}.procure dd a{white-space:normal}}

/* ---- rail progress (assets/rail-progress.js adds .rail-live; without it the rail is the plain list) ----
   Wide: the first list becomes a dendrite track - a hairline down the list, a soma at each section
   link; read sections fill --primary, the current one is the lit soma with a --patina ring, upcoming
   ones are hollow receptors; a thin --patina fill on the track grows to the current soma
   (--rail-fill, px, set per frame). Narrow: a 2px --patina line along the strip's bottom edge
   (--rail-progress, 0..1). Status is never colour alone: aria-current and the number stay. */
.rail-live ul + .rail-h{color:var(--ink-soft)}
.rail-live ul + .rail-h + ul a{font-size:12.5px}
@media (min-width:1100px){
  .rail-live .rail-in > ul:first-of-type{position:relative;--rail-track-top:14px;--rail-track-bottom:14px;--rail-fill:0px}
  .rail-live .rail-in > ul:first-of-type::before,.rail-live .rail-in > ul:first-of-type::after{content:"";position:absolute;left:9px;top:var(--rail-track-top);width:1px;pointer-events:none}
  .rail-live .rail-in > ul:first-of-type::before{bottom:var(--rail-track-bottom);background:var(--rule)}
  .rail-live .rail-in > ul:first-of-type::after{height:var(--rail-fill);background:var(--patina)}
  /* a nested list (ul.rail-sub, /evidence/) is part of the same track: it draws no track of its own over the fill,
     and each sub-entry is a soma on that track, lit by its own li's state (review pin 0mupoh0hllhfkaf) */
  .rail-live .rail-in > ul:first-of-type a{position:relative;border-left:0;padding-left:22px}
  /* the dot sits 5px in: the current one (scaled, with its ring) reaches about 4px past its box, and .rail's
     overflow:auto clipped it at the left edge (review pin 0muldt2uvmpyzd8) */
  .rail-live .rail-in > ul:first-of-type a::before{content:"";position:absolute;left:5px;top:50%;width:7px;height:7px;margin-top:-4.5px;border-radius:50%;background:var(--paper);border:1px solid var(--ink-soft);box-sizing:content-box;transition:background-color .2s,border-color .2s,transform .2s}
  .rail-live .rail-in > ul:first-of-type a:hover{border-left:0}
  .rail-live .rail-in > ul:first-of-type a[aria-current]{border-left:0;padding-left:22px}
  .rail-live .rail-in > ul:first-of-type li.is-read > a::before{background:var(--primary);border-color:var(--primary)}
  .rail-live .rail-in > ul:first-of-type li.is-current > a::before{background:var(--primary);border-color:var(--paper);outline:1.5px solid var(--patina);outline-offset:1px;transform:scale(1.25)}
  .rail-live .rail-in > ul:first-of-type li.is-ahead > a::before{background:var(--paper);border-color:var(--ink-soft)}
}
@media (max-width:1099px){
  .rail-live{--rail-progress:0}
  .rail-live::after{content:"";position:absolute;left:0;bottom:-1px;height:2px;width:calc(var(--rail-progress) * 100%);background:var(--patina);pointer-events:none;transition:width .15s linear}
}
@media (prefers-reduced-motion:reduce){
  .rail-live a::before,.rail-live::after{transition:none}
}

/* ---- reduced motion, print ---- */
@media (prefers-reduced-motion:reduce){
  .rail a{transition:none}
  .fig .f-pulse{animation:none;opacity:1}
  html{scroll-behavior:auto}
}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}
@media print{
  .rail{display:none}
  .spine-layout{display:block}
  .spine-head{padding-left:var(--spine-pad)}
  main .plate{box-shadow:none;border:1px solid var(--ink)}
}

/* ---- practice hub ----
   The shared styles of the practice hubs (story 34-3; template practices/veterinary-diagnostics/, contract
   _build/COMPONENTS.md §11). Everything is scoped under main.hub: 404.html has its own .status, and /problems/
   keeps its page-local status labels. Tokens by name, hairlines only. */
.hub .status-key{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 16px;margin:20px 0 0;max-width:68ch;font-size:14.5px}
.hub .status-key dt,.hub .status-key dd{margin:0}
.hub .status{display:inline-block;align-self:flex-start;font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--primary-deep);border:1px solid var(--primary);border-radius:2px;padding:1px 6px;white-space:nowrap;line-height:1.5}
/* problems we solve: a numbered list whose headings open the /problems/ sections */
.hub .hub-problems{list-style:none;margin:22px 0 18px;padding:0}
.hub .hub-problem{padding:14px 0 16px;border-bottom:1px solid var(--rule)}
.hub .hub-problem:first-child{border-top:1px solid var(--rule)}
.hub .hub-problem h3{font-size:19px;line-height:1.3;margin:0 0 6px;max-width:48ch}
.hub .hub-problem h3 a{text-decoration:none}
.hub .hub-problem h3 a:hover,.hub .hub-problem h3 a:focus-visible{text-decoration:underline}
.hub .hub-problem p{margin:0;font-size:15px;color:var(--ink-soft)}
/* how we approach the work: four short blocks, two across where the column allows */
.hub .hub-approach{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:22px 28px;margin-top:22px}
.hub .hub-approach > div{border-top:2px solid var(--ink);padding-top:12px;min-width:0}
.hub .hub-approach h3{font-size:19px;margin:0 0 8px}
.hub .hub-approach p{font-size:15px;max-width:none}
/* right tool, right job: the cards, then the services block */
.hub .hub-tools{grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr))}
.hub .tool-card .tool-cat{font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft)}
.hub .tool-card h3{margin:0}
.hub .tool-card .tool-problem b,.hub .tool-card .tool-fit b,.hub .tool-card .tool-limit b{display:block;font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--patina-deep);font-weight:600;margin-bottom:2px}
.hub .tool-card .tool-links{margin-top:auto;padding-top:10px;border-top:1px solid var(--rule)}
.hub .hub-services{margin-top:34px;border-top:3px double var(--ink);padding-top:14px}
.hub .hub-services h3{margin:0 0 8px}
.hub .hub-services ul{list-style:none;margin:14px 0 0;padding:0;border-top:1px solid var(--rule)}
.hub .hub-services li{padding:10px 0;border-bottom:1px solid var(--rule);font-size:15px}
/* the held Your team note sits between two sections, not inside one */
.hub .spine > .decision{margin:0 0 4px;max-width:68ch}
/* ways to begin: bounded prose, then the pricing links */
.hub .cost-drivers{max-width:68ch}
.hub .hub-links{font-size:14.5px;border-top:1px solid var(--rule);padding-top:10px}
@media (max-width:520px){.hub .status-key{grid-template-columns:minmax(0,1fr);gap:2px}.hub .status-key dd{margin-bottom:10px}}

/* ---- general problem page ----
   The shared styles of the general problem pages under /problems/<slug>/ (story 34-6; contract _build/COMPONENTS.md
   §12). Everything is scoped under main.problem-page: /problems/ keeps its page-local status labels and the hubs keep
   theirs under main.hub. Tokens by name, hairlines only. */
main.problem-page .status-key{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 16px;margin:20px 0 0;max-width:68ch;font-size:14.5px}
main.problem-page .status-key dt,main.problem-page .status-key dd{margin:0}
main.problem-page .status{display:inline-block;font-family:var(--font-mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--primary-deep);border:1px solid var(--primary);border-radius:2px;padding:1px 6px;margin-right:8px;white-space:nowrap;line-height:1.5}
/* the approach ladder, the tool fits, the evidence items and the practice links: hairline-ruled lists */
main.problem-page .approach-list,main.problem-page .fits,main.problem-page .evidence-items,main.problem-page .practice-links{list-style:none;margin:18px 0 0;padding:0;border-top:1px solid var(--rule)}
main.problem-page .approach-list li,main.problem-page .fits li,main.problem-page .evidence-items li,main.problem-page .practice-links li{padding:10px 0;border-bottom:1px solid var(--rule);font-size:15px}
main.problem-page .approach-list b{font-weight:600;color:var(--ink)}
main.problem-page .fits{margin-top:22px}
main.problem-page .fit-name{font-weight:600;color:var(--ink)}
main.problem-page .fit-when{display:block;margin:4px 0 2px;font-family:var(--font-display);font-style:italic;font-size:16px;line-height:1.4;color:var(--ink-soft)}
main.problem-page .evidence-items + p,main.problem-page .practice-links + p{margin-top:16px}
main.problem-page .problem-page-links{font-size:14.5px;border-top:1px solid var(--rule);padding-top:10px}
@media (max-width:520px){main.problem-page .status-key{grid-template-columns:minmax(0,1fr);gap:2px}main.problem-page .status-key dd{margin-bottom:10px}main.problem-page .status{white-space:normal}}

/* ---- labs we help overview ----
   The Labs we help overview at /practices/ (story 34-8; contract _build/COMPONENTS.md §14). Everything is scoped under
   main.labs-overview: the home page keeps its own practice-card rules. Tokens by name, hairlines only. */
main.labs-overview .practice-grid{grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr))}
main.labs-overview .practice-grid h3{margin:0}
main.labs-overview .practice-for{font-size:15px}
main.labs-overview .practice-problems-h{margin-top:auto;padding-top:10px;border-top:1px solid var(--rule);font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--patina-deep)}
main.labs-overview .practice-problems{list-style:none;margin:0;padding:0}
main.labs-overview .practice-problems li{padding:6px 0;border-bottom:1px solid var(--rule);font-size:14px;line-height:1.45;max-width:none}
main.labs-overview .practice-problems li:last-child{border-bottom:0}

/* ---- product and service pages: practice and problem context (story 34-10) ---- */
.spine-sec .offer-context{margin-top:26px;border-top:1px solid var(--rule);padding-top:4px}
.spine-sec .offer-context h4{font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--patina-deep);margin:16px 0 6px}
.spine-sec .offer-context ul{list-style:none;margin:0;padding:0}
.spine-sec .offer-context li{padding:6px 0;border-bottom:1px solid var(--rule);font-size:15px;max-width:none}
.spine-sec .offer-context li:last-child{border-bottom:0}

/* === sf-home === */
/* /practices/ (team review 2026-09-25): the four cards two by two on wide screens, so Government Research sits beside
   Laboratory Modernization (Sam, pin epbs); the card copy as a short list (Emily, 6fjw 325i s6hq); the See pricing
   button under the intro (Shivam, kbiu). Tokens only. */
main.labs-overview .practice-for{margin:0}
main.labs-overview .practice-scope{margin:0 0 4px;padding-left:1.1em;font-size:15px;line-height:1.5}
main.labs-overview .practice-scope li{margin:2px 0;max-width:none}
main.labs-overview .practices-actions{margin:18px 0 0}
@media (min-width:760px){
  main.labs-overview .practice-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* === end sf-home === */
/* === sf-problems === */
/* site feedback 2026-09-26: problem pages now follow a short list with a paragraph (practice links, the price line) */
main.problem-page .approach-list + p{margin-top:16px}
/* === end sf-problems === */
/* === sf-practices === */
/* Practice hubs, team review 2026-09-26: the industries list moves into the page head when "Who this is for" comes off
   (D136, pin 2uj0), set as a compact row of labels; the tool cards sit two across (pin b9tu). Tokens by name. */
.hub .spine-head .industries-h{font-family:var(--font-mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--patina-deep);margin:22px 0 8px}
.hub .spine-head .industries{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px 8px;max-width:68ch}
.hub .spine-head .industries li{font-size:13.5px;line-height:1.4;color:var(--ink-soft);border:1px solid var(--rule);border-radius:2px;padding:3px 9px;margin:0}
@media (min-width:700px){.hub .hub-tools{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* === end sf-practices === */

/* L5.8: a product screenshot in a hero is unreadable at 340px. On a phone it renders at a legible 640px inside its
   own frame, which pans sideways (the page itself never does). */
@media (max-width:759px){
  .spine-head.hero-fig .hero-media .matte{overflow-x:auto;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;scrollbar-width:thin}
  .spine-head.hero-fig .hero-media .matte > img[src*="assets/screens/"]{width:640px;min-width:640px;max-width:none;height:auto}
}
