/* modern.css: the case files, read in 2026.

   Loaded by the five case files only, after every other stylesheet. It
   changes how the files are presented, never what they say, and it keeps
   the one rule the case files were rebuilt around in v4.0: nothing puts a
   filled or framed tray round prose to give it a rank it has not earned
   (boxes.mjs holds that line). So "modern" here is not cards. It is depth
   and motion on the things that are pictures, a calmer and larger voice
   for the things that are words, and chrome that floats rather than sits.

   1. The sheet floats: rounded, lifted off the desk.
   2. The section bar is a glass pill with a reading-progress line.
   3. The running product is framed as a browser window, with a glow in the
      file's own accent behind it.
   4. Every picture (demo, plate, figure, screenshot) gets the same corner
      and the same soft depth, and rises a few pixels into place as it
      enters the screen.
   5. Body text is set for reading rather than for density.
   6. Annotations speak in sentences rather than in capitals.
   7. The fixes ledger is numbered, the outcome is the loud column, and a
      row lights under the pointer.
   8. The way out of a file is a large link to the next one. */

html[data-file]{
  --cf-r:18px;                 /* the corner, one value for every picture */
  --cf-r-sm:12px;
  --cf-lift:0 1px 2px rgb(0 0 0 / .05), 0 18px 48px -24px rgb(16 24 24 / .32);
  --cf-lift-hi:0 1px 2px rgb(0 0 0 / .06), 0 34px 80px -36px color-mix(in srgb, var(--accent) 55%, rgb(0 0 0 / .5));
  --cf-ease:cubic-bezier(.2,.7,.2,1);
}
html[data-file][data-theme="dark"]{
  --cf-lift:0 1px 2px rgb(0 0 0 / .4), 0 18px 48px -20px rgb(0 0 0 / .7);
  --cf-lift-hi:0 1px 2px rgb(0 0 0 / .5), 0 34px 90px -30px color-mix(in srgb, var(--accent) 40%, rgb(0 0 0 / .8));
}

/* ---- 1. the sheet --------------------------------------------------- */
@media(min-width:861px){
  html[data-file] .doc{
    margin:22px auto 28px;
    border-radius:26px;
    overflow:clip;                 /* clip, not hidden: the section bar stays sticky */
    border-color:color-mix(in srgb, var(--line) 70%, transparent);
    box-shadow:var(--cf-lift);
  }
}

/* ---- 2. the section bar --------------------------------------------- */
html[data-file] .docnav{
  margin:26px auto 0;width:fit-content;max-width:100%;
  justify-content:center;gap:2px;padding:5px;
  border:1px solid color-mix(in srgb, var(--line) 85%, transparent);
  border-radius:999px;
  background:color-mix(in srgb, var(--bg-raised) 72%, transparent);
  -webkit-backdrop-filter:blur(18px) saturate(1.6);
  backdrop-filter:blur(18px) saturate(1.6);
  box-shadow:0 10px 30px -16px rgb(0 0 0 / .28);
}
html[data-file] .docnav a,
html[data-file] .docnav .dn-more > button{
  /* eleven names on one row at 1440 (v7.24): 11px of side padding, and the
     long labels shortened in the markup; two rows read as two bars. From
     v7.36 a row that still does not fit puts its last names under More */
  border-radius:999px;padding:8px 11px;font-size:12.5px;letter-spacing:-.005em;
}
html[data-file] .docnav .dn-menu{border-radius:18px}
html[data-file] .docnav .dn-menu a{border-radius:12px;padding:9px 13px}
html[data-file] .docnav a.on{
  color:var(--accent-text);
  background:var(--accent-soft);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}
/* How far through the file the reader is, drawn under the active pill's
   row. A scroll timeline, so it costs no script and stops when the reader
   does; one iteration, so rule 3 (nothing loops on its own) still holds. */
@supports (animation-timeline: scroll()){
  html[data-file] .docnav::after{
    content:'';position:absolute;left:22px;right:22px;bottom:-1px;height:2px;border-radius:2px;
    background:linear-gradient(90deg, color-mix(in srgb, var(--accent) 40%, transparent), var(--accent));
    transform-origin:0 50%;transform:scaleX(0);
    animation:cf-progress linear both;animation-timeline:scroll(nearest block);
    pointer-events:none;
  }
}
@keyframes cf-progress{to{transform:scaleX(1)}}
@media(max-width:700px){
  html[data-file] .docnav{border-radius:20px;margin-top:14px;padding:4px;justify-content:flex-start;width:auto}
  html[data-file] .docnav a{padding:7px 9px;font-size:11.5px}
  /* the progress line is drawn under the bar and the mask would cut it */
  html[data-file] .docnav::after{display:none}
}

/* ---- 3. the running product, as a window ---------------------------- */
html[data-file] .doc .launch{
  position:relative;isolation:isolate;
  margin:52px 0 0;
  border:1px solid color-mix(in srgb, var(--line) 90%, transparent);
  border-radius:var(--cf-r);
  overflow:clip;
  background:var(--bg-raised);
  box-shadow:var(--cf-lift-hi);
}
html[data-file] .doc .launchbar{
  padding:11px 16px 10px;gap:12px;
  border-bottom:1px solid var(--line);
}
/* Three lights, drawn rather than imported: the frame says "this is a
   program running", which is what it is. */
html[data-file] .doc .launchbar::before{
  content:'';flex:none;width:44px;height:10px;
  background:
    radial-gradient(circle at 5px 5px, #ff5f57 4.4px, transparent 5px),
    radial-gradient(circle at 22px 5px, #febc2e 4.4px, transparent 5px),
    radial-gradient(circle at 39px 5px, #28c840 4.4px, transparent 5px);
}
html[data-file] .doc .launchbar .dot{display:none}
html[data-file] .doc .launch .stage{border-radius:0}
html[data-file] .doc .launchcap{padding:10px 16px}
html[data-file] .doc .launcha11y{padding:8px 16px 4px}
html[data-file] .doc .launchweight{padding:0 16px 4px}
html[data-file] .doc .launchstates{padding:0 16px 10px}
html[data-file] .doc .launchsmall img{border-radius:var(--cf-r-sm);box-shadow:var(--cf-lift)}
/* First under the hero since v7.22: the navigator sits between, and the
   window follows it closely rather than at a section's distance. */
html[data-file] .doc .docnav + .launch{margin-top:22px}
@media(max-width:860px){
  html[data-file] .doc .launch{margin:40px 0 0;border-radius:14px}
  html[data-file] .doc .docnav + .launch{margin-top:16px}
}

/* ---- 4. pictures ---------------------------------------------------- */
/* hidden, not clip: hidden also makes the frame a formatting context, so
   it sits beside a floated margin note instead of running under it. The
   first pass used clip and the before/after demo slid under its note. */
html[data-file] .doc .demo,
html[data-file] .doc .embed{
  border-radius:var(--cf-r);
  overflow:hidden;
  box-shadow:var(--cf-lift);
}
html[data-file] .doc .secplate-box{
  border-radius:var(--cf-r-sm);
  overflow:clip;
}
html[data-file] .doc figure.fig img,
html[data-file] .doc .fig > img,html[data-file] .doc .fig > picture > img{
  border-radius:var(--cf-r-sm);
  box-shadow:var(--cf-lift);
}
/* Rises a few pixels into place as it enters. Transform only: an element
   that fades from nothing reads as missing to anything that measures
   contrast before it has been scrolled to, and a picture that is not there
   yet is worse than one that does not move. */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline: view()){
    html[data-file] .doc :is(.demo, .embed, figure.secplate, figure.fig, .launch){
      animation:cf-rise linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 70%;
    }
    /* The one being linked to does not rise. A fragment scroll aligns the
       box as it is at that moment, and at that moment the launch window
       was still 34px down its rise, so a link to #try landed it under the
       docnav by exactly that much. */
    html[data-file] .doc .launch:target{animation:none}
  }
}
@keyframes cf-rise{from{transform:translateY(34px) scale(.985)}to{transform:none}}

/* ---- 5. reading ----------------------------------------------------- */
html[data-file] .doc .prose p{font-size:15.5px;line-height:1.72;max-width:68ch}
html[data-file] .doc .prose p + p{margin-top:12px}
html[data-file] .doc .sec > .standfirst{letter-spacing:-.012em}
html[data-file] .doc .sec h2{text-wrap:balance}

/* ---- 6. annotations ------------------------------------------------- */
/* The callouts on the figures were set in spaced monospace capitals, four
   lines deep. Capitals are for a word or two; a sentence in them is read a
   letter at a time. The title keeps the small caps; the sentence under it
   is a sentence. */
html[data-file] .doc .hudnote{
  font:400 12.5px/1.5 var(--ui);letter-spacing:0;text-transform:none;
  color:var(--text-2);
}
html[data-file] .doc .hudnote b{
  font:600 max(10px,var(--floor))/1.4 var(--mono);letter-spacing:.08em;text-transform:uppercase;
  color:var(--text);margin-bottom:3px;
}
html[data-file] .doc .hudrail{letter-spacing:.1em}
html[data-file] .doc .secplate > figcaption,
html[data-file] .doc figure.fig > figcaption{font-family:var(--ui);letter-spacing:0}

/* ---- 7. the fixes ledger -------------------------------------------- */
html[data-file] .doc .fixes{counter-reset:cf-fix;margin-top:22px}
html[data-file] .doc .fixhead,
html[data-file] .doc .fix{position:relative;padding-left:46px;column-gap:30px}
/* Square: each row carries a top rule, and a rounded row bends that rule
   into an arc at both ends. */
html[data-file] .doc .fix{
  counter-increment:cf-fix;
  transition:background-color .25s var(--cf-ease);
}
html[data-file] .doc .fix::before{
  content:counter(cf-fix, decimal-leading-zero);
  position:absolute;left:12px;top:20px;
  font:500 11px/1 var(--mono);letter-spacing:.04em;color:var(--text-3);
}
html[data-file] .doc .fix:hover{background:color-mix(in srgb, var(--accent-soft) 70%, transparent)}
html[data-file] .doc .fix > div{padding:18px 0}
html[data-file] .doc .fix p{font-size:13.5px;line-height:1.6}
html[data-file] .doc .fix .n{font-size:clamp(20px,2vw,26px);letter-spacing:-.025em;margin-bottom:5px}
@media(max-width:760px){
  html[data-file] .doc .fixhead,
  html[data-file] .doc .fix{padding-left:0}
  html[data-file] .doc .fix::before{position:static;display:block;padding-top:16px}
}

/* ---- 8. the way out ------------------------------------------------- */
html[data-file] .doc .pager{gap:14px;margin-top:40px}
html[data-file] .doc .pager a{
  border-radius:var(--cf-r);padding:22px 24px;
  transition:border-color .25s var(--cf-ease), transform .25s var(--cf-ease), box-shadow .25s var(--cf-ease);
}
html[data-file] .doc .pager a:hover{transform:translateY(-2px);box-shadow:var(--cf-lift)}
html[data-file] .doc .pager .dir,
html[data-file] .doc .pager .name{display:block}
html[data-file] .doc .pager .name{
  font:700 clamp(16px,1.7vw,21px)/1.22 var(--display);letter-spacing:-.022em;margin-top:8px;
}

@media print{
  html[data-file] .doc{border-radius:0;box-shadow:none;overflow:visible}
  html[data-file] .doc .launch,
  html[data-file] .doc .demo,
  html[data-file] .doc .embed{box-shadow:none}
  html[data-file] .doc *{animation:none !important}
}


/* ---- a still beside the prose (v7.23) ---------------------------------
   Shad's note: wall of text for pages, put an image beside it, make the
   image where there is none. Each prose block that had no picture now has
   the running product beside it, opened in the state the section is about,
   shot by the stills tool. Two columns from 1000px, the still sticky so it
   stays beside the paragraph being read; stacked below it on a phone. */
html[data-file] .doc .prosestill{display:grid;grid-template-columns:minmax(0,1fr);gap:22px;align-items:start;margin-top:4px}
@media(min-width:1000px){
  html[data-file] .doc .prosestill{grid-template-columns:minmax(0,11fr) minmax(0,9fr);gap:36px}
  html[data-file] .doc .prosestill .still{position:sticky;top:calc(var(--viewhead-real,var(--viewhead)) + 70px)}
}
html[data-file] .doc .still{margin:0;border:1px solid var(--line);border-radius:var(--cf-r-sm,8px);overflow:hidden;background:var(--bg-raised);box-shadow:var(--cf-lift)}
html[data-file] .doc .still img{display:block;width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;object-position:top}
/* the still is a door (v7.25): it opens the product in the state it shows */
html[data-file] .doc .still a.open{display:block;position:relative}
html[data-file] .doc .still a.open::after{content:'Open this state \2197';position:absolute;right:10px;bottom:10px;padding:5px 9px;border-radius:999px;background:var(--btn,var(--accent));color:#ffffff;font:600 max(10.5px,var(--floor)) var(--ui);opacity:0;transform:translateY(4px);transition:opacity var(--snap),transform var(--snap)}
html[data-file] .doc .still a.open:hover::after,html[data-file] .doc .still a.open:focus-visible::after{opacity:1;transform:none}
@media(hover:none){html[data-file] .doc .still a.open::after{opacity:1;transform:none}}
html[data-file] .doc .still figcaption{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:9px 12px;border-top:1px solid var(--line);font:400 11.5px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc .still figcaption span{flex:none;font:600 max(9px,var(--floor)) var(--mono);letter-spacing:.1em;color:var(--text-3)}
html[data-file] .doc .sec.ground .still{background:color-mix(in srgb, var(--on-ground) 6%, transparent)}
html[data-file] .doc .still.wide{max-width:820px;margin-top:20px}
/* ---- phone stills (v7.27) -----------------------------------------------
   The two phone apps are shot at phone size (.still.mobile: not .phone,
   which is the case file's bezel). A phone still keeps its own
   shape, which the shape suite reads, and sits at a phone's width: two
   share a row under the design section's standfirst, and in the outcome
   the dashboard's booking and the phone it lands on stack in the sticky
   column, so the reader sees both ends of the same act. */
html[data-file] .doc .still.mobile{max-width:280px}
html[data-file] .doc .still.mobile img{aspect-ratio:390/844;object-fit:fill}
/* a phone still is narrow, so its caption's mono label goes under the
   sentence rather than beside it, where the clip suite found it cut */
html[data-file] .doc .still.mobile figcaption{flex-direction:column;align-items:flex-start;gap:5px}
html[data-file] .doc .phonestills{display:grid;grid-template-columns:repeat(2,minmax(0,280px));gap:22px;justify-content:start;margin-top:20px}
@media(max-width:700px){html[data-file] .doc .phonestills{grid-template-columns:minmax(0,280px);justify-content:center}}
html[data-file] .doc .stillstack{display:grid;gap:16px;justify-items:center}
html[data-file] .doc .stillstack .still{width:100%}
html[data-file] .doc .stillstack .still.mobile{max-width:240px}
@media(min-width:1000px){
  html[data-file] .doc .prosestill .stillstack{position:sticky;top:calc(var(--viewhead-real,var(--viewhead)) + 70px)}
  html[data-file] .doc .prosestill .stillstack .still{position:static}
}

/* --- read in full, or skim (v7.30, wave 1 round 4) ------------------------
   The minutes are counted by tools/build-reading-time.mjs at 238 words a
   minute (Brysbaert, 2019) plus Medium's allowance per figure, and written
   into the header. app.js turns the line into two buttons; with no script
   it stays a line of text and the file stays whole.

   The skim folds what a skimming reader would pass over anyway: the long
   prose, the hand-written notes, the spec tables. The headings, every
   standfirst, the facts, the numbers, the figures and their captions, the
   pull quotes and the decisions stay. This selector list is the tool's
   SKIM_HIDE, and the readtime suite fails if the two drift apart. Screen
   only: a printed file is always the whole file. */
.doc > header.casehead > .readtime{
  position:relative;z-index:2;
  max-width:48%;
  margin:16px 0 0;
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  /* as tall as the two buttons app.js puts here, from the first paint: the
     plain line is one 15px row and the buttons are 30px, and the whole
     file under them moved down 14px when they arrived (v7.49) */
  min-height:30px;
  font:500 max(10.5px,var(--floor))/1.4 var(--mono);letter-spacing:.07em;text-transform:uppercase;
  color:color-mix(in srgb, var(--on-ground) 72%, transparent);
}
.readtime .rtbtn{
  font:inherit;letter-spacing:inherit;text-transform:inherit;
  color:var(--on-ground);background:transparent;cursor:pointer;
  border:1px solid color-mix(in srgb, var(--on-ground) 36%, transparent);
  border-radius:999px;padding:6px 12px;min-height:30px;
}
.readtime .rtbtn:hover{border-color:var(--on-ground)}
.readtime .rtbtn[aria-pressed="true"]{background:var(--on-ground);color:var(--ground);border-color:var(--on-ground)}
.readtime .rtbtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media(max-width:860px){.doc > header.casehead > .readtime{max-width:none}}
@media screen{
  html[data-read="skim"] .doc .prose,
  html[data-read="skim"] .doc .handnote,
  html[data-read="skim"] .doc .fixes,
  html[data-read="skim"] .doc section.sec > p:not(.standfirst){display:none}
  /* a still that sat beside its prose stands alone, at reading width */
  html[data-read="skim"][data-file] .doc .prosestill{grid-template-columns:minmax(0,1fr);max-width:820px}
  html[data-read="skim"][data-file] .doc .prosestill .still{position:static}
}
@media print{.readtime,.doc > header.casehead > .readtime{display:none}}

/* What I would do differently (v7.31, wave 2 round 13): the close of every
   outcome section, numbered, a lead in bold and the reason after it. */
html[data-file] .doc .hindsight{margin-top:38px;padding-top:24px;border-top:1px solid var(--line);scroll-margin-top:calc(var(--viewhead-real,var(--viewhead)) + 70px)}
html[data-file] .doc .hindsight ol{list-style:none;counter-reset:hs;margin:14px 0 0;padding:0;display:grid;gap:14px;max-width:72ch}
html[data-file] .doc .hindsight li{counter-increment:hs;position:relative;padding-left:36px;font:400 15px/1.6 var(--ui);color:var(--text-2)}
html[data-file] .doc .hindsight li::before{content:counter(hs,decimal-leading-zero);position:absolute;left:0;top:3px;font:600 11px/1 var(--mono);letter-spacing:.06em;color:var(--accent-text)}
html[data-file] .doc .hindsight li b{color:var(--text);font-weight:600}

/* The result against the bar (v7.31, wave 2 round 15): every outcome opens
   on the measures the file set, each with what happened to it. On a phone
   the rows become cards, the column names carried by data labels. */
html[data-file] .doc table.bar{width:100%;max-width:900px;margin:18px 0 26px;border-collapse:collapse;font:400 14px/1.5 var(--ui);color:var(--text)}
html[data-file] .doc table.bar caption{caption-side:top;text-align:left;padding:0 0 10px;font:500 max(10px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-2)}
html[data-file] .doc table.bar th{text-align:left;font:500 max(9.5px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:8px 14px 8px 0;border-bottom:1px solid var(--line-strong)}
html[data-file] .doc table.bar td{vertical-align:top;padding:11px 14px 11px 0;border-bottom:1px solid var(--line)}
html[data-file] .doc table.bar td:first-child{font-weight:600;width:34%}
html[data-file] .doc table.bar td:last-child{width:1%;white-space:nowrap;padding-right:0}
.barst{display:inline-block;font:600 max(9.5px,var(--floor))/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;padding:5px 7px;border-radius:3px;border:1px solid currentColor;color:var(--accent-text)}
.barst[data-st="held"]{color:var(--text-2)}
.barst[data-st="none"]{color:var(--text-3);border-style:dashed}
@media screen and (max-width:760px){
  html[data-file] .doc table.bar tr{display:grid;grid-template-columns:1fr auto;gap:4px 10px;padding:12px 0;border-bottom:1px solid var(--line)}
  html[data-file] .doc table.bar td{display:block;padding:0;border:0;width:auto}
  html[data-file] .doc table.bar td:first-child{grid-column:1;width:auto}
  html[data-file] .doc table.bar td:nth-child(2){grid-column:1 / -1;grid-row:2;color:var(--text-2)}
  html[data-file] .doc table.bar td:last-child{grid-column:2;grid-row:1}
}
@media print{html[data-file] .doc table.bar{break-inside:avoid}}

/* The case in seven questions (v7.31, wave 2 round 16): problem, people,
   constraints, explorations, decision, result, reflection, each a jump to
   the part of the file that answers it. Under the section nav, not sticky:
   it is an index for the first visit, the section nav is for the rest. */
html[data-file] .doc nav.modules{display:flex;flex-wrap:wrap;align-items:center;gap:6px 6px;margin:2px 0 22px;justify-content:center}
html[data-file] .doc nav.modules .mk{font:500 max(9.5px,var(--floor))/1.2 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);margin-right:6px}
html[data-file] .doc nav.modules a{font:500 11px/1 var(--mono);letter-spacing:.05em;text-transform:uppercase;color:var(--text-2);padding:7px 9px;min-height:26px;display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:999px;text-decoration:none}
html[data-file] .doc nav.modules a:hover{color:var(--text);border-color:var(--line-strong)}
html[data-file] .doc nav.modules a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
html[data-file] .doc .casefacts{scroll-margin-top:calc(var(--viewhead-real,var(--viewhead)) + 70px)}
@media(max-width:700px){html[data-file] .doc nav.modules{justify-content:flex-start}html[data-file] .doc nav.modules .mk{flex-basis:100%}}
@media print{html[data-file] .doc nav.modules{display:none}}

/* See also (v7.31, wave 2 round 17): two files that argue the same thing
   from another side, each with the reason, after the outcome. */
html[data-file] .doc aside.seealso{margin:30px 0 34px;padding:20px 0 0;border-top:1px solid var(--line)}
html[data-file] .doc aside.seealso .sah{font:500 max(10px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);margin:0 0 12px}
html[data-file] .doc aside.seealso ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
html[data-file] .doc aside.seealso a{display:block;height:100%;padding:14px 16px;border:1px solid var(--line);border-radius:10px;text-decoration:none;color:var(--text)}
html[data-file] .doc aside.seealso a:hover{border-color:var(--line-strong)}
html[data-file] .doc aside.seealso a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
html[data-file] .doc aside.seealso b{display:block;font:650 15px/1.3 var(--display);margin-bottom:4px}
html[data-file] .doc aside.seealso span{display:block;font:400 13px/1.5 var(--ui);color:var(--text-2)}
@media(max-width:700px){html[data-file] .doc aside.seealso ul{grid-template-columns:1fr}}

/* One labelling system on a case file (v7.32, wave 3 round 26).
   A diagram carried four labels (its number and title on the rail, a second
   strapline on the rail, the caption, and an uppercase tag after the
   caption) and every section closed on a footer naming the next one, which
   the section nav already does. Three systems were speaking at once. A case
   file now labels with one: the section's number and name, the figure's
   number and title, and the caption in prose. The rest is hidden here
   rather than deleted, so the markup keeps its record. */
html[data-file] .doc .figrail > span:last-child:not(:first-child),
html[data-file] .doc figcaption > span:not([class]):last-child,
html[data-file] .doc .launchcap > span:not([class]):last-child,
html[data-file] .doc .secfoot{display:none}

/* A case file on paper, and in its PDF (v7.32, wave 3 round 30). The
   workspace chrome is for a pointer: the navigator, the search, the theme
   switch, the copy button, the clocks, the section pills and the status
   line meant nothing printed, and the first page of each PDF opened on
   them. Paper keeps the name, the path and the file's number, then the
   file. */
@media print{
  html[data-file] .topbar .navbtn, html[data-file] .topbar .topnav, html[data-file] .topbar .right,
  html[data-file] .sidenav, html[data-file] .statusbar, html[data-file] .toast,
  html[data-file] .viewhead .vh-actions, html[data-file] .viewhead .clock,
  html[data-file] .doc nav.docnav{display:none}
  /* a section number or heading never ends a page on its own */
  html[data-file] .doc .sec .plateno, html[data-file] .doc .sec h2, html[data-file] .doc .sec h3{break-after:avoid}
}

/* Before and after on case file 003 (v7.33): what the old notes system
   assumed against what the new tool does, each line a link into the tool. */
html[data-file] .doc table.shifttable{width:100%;max-width:900px;margin:14px 0 26px;border-collapse:collapse;font:400 14px/1.5 var(--ui)}
html[data-file] .doc table.shifttable th{text-align:left;font:500 max(10px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:8px 14px 8px 0;border-bottom:1px solid var(--line-strong)}
html[data-file] .doc table.shifttable td{vertical-align:top;padding:11px 14px 11px 0;border-bottom:1px solid var(--line)}
html[data-file] .doc table.shifttable td:first-child{width:38%;color:var(--text-2)}
html[data-file] .doc table.shifttable td a{white-space:nowrap}
@media screen and (max-width:760px){
  html[data-file] .doc table.shifttable tr{display:grid;gap:4px;padding:12px 0;border-bottom:1px solid var(--line)}
  html[data-file] .doc table.shifttable td{display:block;width:auto;padding:0;border:0}
  html[data-file] .doc table.shifttable td:first-child{width:auto}
  html[data-file] .doc table.shifttable td:first-child::before{content:'Before: '}
}
@media print{html[data-file] .doc table.shifttable{break-inside:avoid}}

/* Research made visible on case file 003 (v7.33, wave 4): the three interview
   scripts side by side, both surveys on one scale, and the usability tasks
   with their intervals. */
html[data-file] .doc .scripts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:12px 0 26px;max-width:960px}
html[data-file] .doc .scripts h4{font:600 13.5px/1.3 var(--ui);margin:0 0 6px;padding-bottom:6px;border-bottom:1px solid var(--line-strong)}
html[data-file] .doc .scripts ul{margin:0;padding-left:16px;font:400 13.5px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc .scripts li+li{margin-top:4px}
html[data-file] .doc .surveybars{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:28px;margin:12px 0 26px;max-width:960px}
html[data-file] .doc .surveybars h4{font:600 13.5px/1.3 var(--ui);margin:0 0 8px;display:flex;justify-content:space-between;gap:10px}
html[data-file] .doc .surveybars h4 span{font:500 max(10.5px,var(--floor)) var(--mono);color:var(--text-3)}
html[data-file] .doc .surveybars ol{list-style:none;margin:0;padding:0}
html[data-file] .doc .surveybars li{display:grid;grid-template-columns:minmax(0,1fr) 128px;gap:10px;align-items:center;padding:7px 0;border-top:1px solid var(--line)}
html[data-file] .doc .surveybars .q{font:400 13px/1.4 var(--ui);color:var(--text-2)}
html[data-file] .doc .surveybars .q small{display:block;margin-top:2px;font:400 12.5px/18px var(--ui);color:var(--accent-text)}
html[data-file] .doc .surveybars li.mark .q{color:var(--text);font-weight:500}
html[data-file] .doc .surveybars .sv{display:grid;grid-template-columns:1fr 40px;gap:6px;align-items:center}
html[data-file] .doc .surveybars .sv i{display:block;height:8px;border-radius:2px;background:linear-gradient(90deg,var(--text-3) var(--v),var(--line) var(--v))}
html[data-file] .doc .surveybars li.mark .sv i{background:linear-gradient(90deg,var(--accent) var(--v),var(--line) var(--v))}
html[data-file] .doc .surveybars li.mark .sv b{color:var(--accent-text)}
html[data-file] .doc .surveybars .sv b{font:600 13px var(--mono);text-align:right}
/* a link in a chart table is a target of at least 24px on a phone (v7.37) */
html[data-file] .doc table.charttable td > a{display:inline-block;min-height:24px;padding:3px 0;line-height:18px}
html[data-file] .doc table.tasktable{width:100%;max-width:960px;margin:14px 0 26px;border-collapse:collapse;font:400 13.5px/1.5 var(--ui)}
html[data-file] .doc table.tasktable caption{caption-side:top;text-align:left;padding:0 0 10px;font:500 max(10px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-2)}
html[data-file] .doc table.tasktable th{text-align:left;font:500 max(10px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:8px 14px 8px 0;border-bottom:1px solid var(--line-strong)}
html[data-file] .doc table.tasktable td{vertical-align:top;padding:11px 14px 11px 0;border-bottom:1px solid var(--line)}
html[data-file] .doc table.tasktable td:first-child{width:44%}
html[data-file] .doc table.tasktable td:nth-child(2){white-space:nowrap;color:var(--text-2)}
html[data-file] .doc table.tasktable .ci{display:block;font:500 max(10.5px,var(--floor)) var(--mono);color:var(--text-3);margin:3px 0}
@media screen and (max-width:760px){
  html[data-file] .doc .scripts, html[data-file] .doc .surveybars{grid-template-columns:1fr}
  html[data-file] .doc table.tasktable tr{display:grid;gap:4px;padding:12px 0;border-bottom:1px solid var(--line)}
  html[data-file] .doc table.tasktable td{display:block;width:auto !important;padding:0;border:0;white-space:normal !important}
}
@media print{html[data-file] .doc .surveybars, html[data-file] .doc table.tasktable{break-inside:avoid}}
/* The measurement plan on 002 (v7.38): three columns of prose, so the second
   is not held to one line the way a job story's situation is */
html[data-file] .doc table.plantable td:first-child{width:26%}
html[data-file] .doc table.plantable td:nth-child(2){white-space:normal}
html[data-file] .doc table.plantable code{font:500 max(11.5px,var(--floor)) var(--mono);color:var(--text)}
/* The split check under 002's test (v7.38): a rule above, not a box */
html[data-file] .doc .srm{max-width:960px;margin:4px 0 26px;padding-top:14px;border-top:1px solid var(--line)}
html[data-file] .doc .srmform{display:flex;flex-wrap:wrap;gap:12px 20px;margin:12px 0 10px}
html[data-file] .doc .srmform label{display:flex;flex-direction:column;gap:5px;font:500 max(10.5px,var(--floor))/1.3 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
html[data-file] .doc .srmform input{width:12ch;min-height:44px;padding:8px 10px;font:400 15px/1.2 var(--ui);color:var(--text);background:var(--bg-raised);border:1px solid var(--line-strong);border-radius:8px;letter-spacing:0;text-transform:none}
html[data-file] .doc .srm output{display:block;font:400 14.5px/1.55 var(--ui);color:var(--text-2)}
html[data-file] .doc .srm[data-verdict="broken"] output{color:var(--text);font-weight:500}

/* The synthesis board (v7.33): the deck's insight cards by corner, each with
   its evidence and the product state it became. */
html[data-file] .doc .synth{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:12px 0 26px;max-width:960px;align-items:start}
html[data-file] .doc .synth h4{font:600 13.5px/1.3 var(--ui);margin:0 0 8px;padding-bottom:6px;border-bottom:1px solid var(--line-strong)}
html[data-file] .doc .synth article{padding:10px 0 6px}
html[data-file] .doc .synth article+article{border-top:1px solid var(--line);margin-top:4px}
html[data-file] .doc .synth article b{display:block;font:600 14px/1.3 var(--ui);color:var(--text)}
html[data-file] .doc .synth article p{margin:6px 0 8px;font:400 13px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc .synth article a{display:block;width:fit-content;min-height:24px;padding:3px 0;font:500 12.5px/18px var(--ui);color:var(--accent-text);text-decoration:underline;text-underline-offset:2px}
@media screen and (max-width:900px){html[data-file] .doc .synth{grid-template-columns:1fr}}
@media print{html[data-file] .doc .synth article{break-inside:avoid}}

/* Job stories (v7.33): when, I want, so I can; one per person. */
html[data-file] .doc ul.jobs{list-style:none;margin:12px 0 26px;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 22px;max-width:960px}
html[data-file] .doc ul.jobs li{font:400 14px/1.55 var(--ui);color:var(--text);padding:10px 0 0;border-top:1px solid var(--line-strong)}
html[data-file] .doc ul.jobs li span{display:block;margin-bottom:4px;font:500 max(10.5px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3)}
@media screen and (max-width:760px){html[data-file] .doc ul.jobs{grid-template-columns:1fr}}

/* The iteration strip (v7.33): five passes, left to right on a desk, a
   column on a phone, each with what it changed. */
html[data-file] .doc ol.passes{list-style:none;margin:14px 0 26px;padding:0;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:0;max-width:1040px;counter-reset:none}
html[data-file] .doc ol.passes li{position:relative;padding:12px 16px 4px 0;border-top:2px solid var(--line-strong);font:400 13px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc ol.passes li:last-child{border-top-color:var(--accent)}
html[data-file] .doc ol.passes li span{display:block;font:500 max(10.5px,var(--floor))/1.3 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);margin-bottom:6px}
html[data-file] .doc ol.passes li b{display:block;font:600 14px/1.3 var(--ui);color:var(--text);margin-bottom:4px}
html[data-file] .doc ol.passes li a{color:var(--accent-text);text-decoration:underline;text-underline-offset:2px}
@media screen and (max-width:900px){
  html[data-file] .doc ol.passes{grid-template-columns:1fr}
  html[data-file] .doc ol.passes li{padding:12px 0 10px}
}
@media print{html[data-file] .doc ol.passes{break-inside:avoid}}

/* The AI chapter on 001 (v7.35): one prompt beside what each of its lines is
   for, and the failures as a ruled list. */
html[data-file] .doc .annot{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:22px;max-width:1000px;margin:12px 0 26px;align-items:start}
html[data-file] .doc .annot pre.prompt{margin:0;padding:4px 0 4px 16px;border-left:2px solid var(--accent);font:400 12.5px/1.6 var(--mono);color:var(--text);white-space:pre-wrap;overflow-wrap:anywhere}
html[data-file] .doc .annot ol.notes{margin:0;padding:0;list-style:none;counter-reset:an}
html[data-file] .doc .annot ol.notes li{counter-increment:an;position:relative;padding:9px 0 9px 30px;border-top:1px solid var(--line);font:400 13.5px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc .annot ol.notes li::before{content:counter(an);position:absolute;left:0;top:11px;font:500 max(11px,var(--floor)) var(--mono);color:var(--accent-text)}
html[data-file] .doc .annot ol.notes li b{display:block;font:600 14px/1.35 var(--ui);color:var(--text);margin-bottom:2px}
@media screen and (max-width:900px){html[data-file] .doc .annot{grid-template-columns:1fr}}
@media print{html[data-file] .doc .annot{break-inside:avoid}}
html[data-file] .doc table.aipatterns td:first-child{width:20%}
html[data-file] .doc table.aipatterns td:nth-child(2){white-space:normal;color:var(--text)}
html[data-file] .doc table.aipatterns td:nth-child(3){width:24%;color:var(--text-2)}
/* The chain, counted, on 001 (v7.39): a bar per depth, its width the share
   of the largest, the number and the words printed beside it */
html[data-file] .doc .chaincount{max-width:960px;margin:22px 0 28px}
html[data-file] .doc ol.chainbars{list-style:none;margin:12px 0 14px;padding:0;display:grid;gap:8px}
html[data-file] .doc ol.chainbars li{display:grid;grid-template-columns:minmax(64px,auto) 1fr;align-items:baseline;gap:4px 14px;font:400 14px/1.45 var(--ui);color:var(--text-2)}
html[data-file] .doc ol.chainbars li b{font:600 18px/1.2 var(--ui);color:var(--text);font-variant-numeric:tabular-nums;text-align:right}
html[data-file] .doc ol.chainbars li::after{content:'';grid-column:2;height:6px;width:max(3px,var(--w));border-radius:3px;background:var(--accent)}
html[data-file] .doc .chainex{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 8px;font:400 13.5px/1.5 var(--ui);color:var(--text-2)}
html[data-file] .doc .chainex .k{width:100%;font:500 max(10.5px,var(--floor))/1.3 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
html[data-file] .doc .chainex code{font:500 max(12px,var(--floor)) var(--mono);color:var(--text);overflow-wrap:anywhere}
html[data-file] .doc .chainex i{font-style:normal;color:var(--text-3)}



/* ---- v7.48: the cool layer on a case file --------------------------- */

/* the section bar's pill slides to the open section (stagecraft 22):
   app.js writes where the lit name is, this draws a pill there and lets
   it move, and the name's own ground goes so there is one pill, not two */
html[data-file] .docnav[data-slide]::before{
  content:'';position:absolute;z-index:0;inset-block:5px;left:var(--dn-x,0px);width:var(--dn-w,0px);
  border-radius:999px;background:var(--accent-soft);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
  transition:left .36s cubic-bezier(.2,.7,.2,1),width .36s cubic-bezier(.2,.7,.2,1);
  pointer-events:none;
}
html[data-file] .docnav[data-slide] a.on{background:none;box-shadow:none}
html[data-file] .docnav[data-slide] > a,html[data-file] .docnav[data-slide] .dn-more{position:relative;z-index:1}
@media(max-width:700px){html[data-file] .docnav[data-slide]::before{inset-block:4px}}
@media(prefers-reduced-motion:reduce){html[data-file] .docnav[data-slide]::before{transition:none}}

/* the running product's window: its three lights come up under the hand */
html[data-file] .doc .launchbar::before{opacity:.62;transition:opacity var(--snap)}
html[data-file] .doc .launch:hover .launchbar::before,html[data-file] .doc .launch:focus-within .launchbar::before{opacity:1}

@media(hover:hover){
  /* the fixes and the bar: the pointed row reads, the rest recede */
  html[data-file] .doc .fix p,html[data-file] .doc .fix p b,html[data-file] .doc table.bar td{transition:color var(--snap)}
  html[data-file] .doc .fixes:has(.fix:hover) .fix:not(:hover) p{color:var(--text-3)}
  html[data-file] .doc .fixes:has(.fix:hover) .fix:not(:hover) p b{color:var(--text-2)}
  html[data-file] .doc table.bar tbody:has(tr:hover) tr:not(:hover) td{color:var(--text-3)}
  /* see also: the title answers */
  html[data-file] .doc aside.seealso b{transition:color var(--snap)}
  html[data-file] .doc aside.seealso a:hover b{color:var(--accent-text)}
  /* a still breathes under the hand (the wide ones are scrubbed by the
     scroll in stagecraft 7 and keep their transform to themselves) */
  html[data-file] .doc figure.still:not(.wide) a.open img{transition:transform .5s cubic-bezier(.2,.7,.2,1)}
  html[data-file] .doc figure.still:not(.wide) a.open:hover img{transform:scale(1.025)}
  /* the seven questions light in turn */
  html[data-file] .doc nav.modules a{transition:color var(--snap),border-color var(--snap)}
  html[data-file] .doc nav.modules:has(a:hover) a:not(:hover){color:var(--text-3)}
  /* a diagram's station reads when pointed at, the rest recede */
  html[data-file] .doc .diagram.plate2 .stn{transition:opacity var(--snap)}
  html[data-file] .doc .diagram.plate2:has(.stn:hover) .stn:not(:hover){opacity:.55}
  /* the phone frames tilt (stagecraft 16): the stage gives them depth */
  html[data-file] .doc .phones{perspective:1200px}
}
html[data-file] .docnav[data-slide] .dn-more > button.on{background:none;box-shadow:none}

/* ------------------------------------------------------------
   v7.50: the case files' own pieces (site.css carries the shared ones
   and the law; app.js the keys, the share and picture-in-picture
   buttons; the sources' dimming is in dossier.css, shared with About)
   ------------------------------------------------------------ */
/* the section bar's names take full ink while the bar is stuck to the
   top (the scroll-state query, Chrome; elsewhere the bar is as it was) */
html[data-file] .docnav{container-type:scroll-state}
@container scroll-state(stuck:top){
  html[data-file] .docnav a:not(.on){color:var(--text)}
}
/* on a phone the bar snaps pill to pill as it scrolls sideways (its own
   scroll, not the page's, so Lenis is not in the way) */
@media(max-width:700px){
  html[data-file] .docnav{scroll-snap-type:x proximity;scroll-padding-inline:8px}
  html[data-file] .docnav a{scroll-snap-align:start}
}
/* the picture-in-picture button sits under the recording's caption */
html[data-file] .doc figure.clip .btn.pip{margin-top:10px}
@media(hover:hover){
  /* a hand-written note takes the accent and its signature lights */
  html[data-file] .doc .handnote{transition:border-color var(--snap)}
  html[data-file] .doc .handnote:hover{border-left-color:var(--accent)}
  html[data-file] .doc .handnote .sig{transition:color var(--snap)}
  html[data-file] .doc .handnote:hover .sig{color:var(--accent-text)}
  /* a note's number steps forward */
  html[data-file] .doc .annot ol.notes li::before{transition:translate var(--snap)}
  html[data-file] .doc .annot ol.notes li:hover::before{translate:3px 0}
  /* a pass lights its rule, and the others recede */
  html[data-file] .doc ol.passes li{transition:border-color var(--snap),color var(--snap)}
  html[data-file] .doc ol.passes li:hover{border-top-color:var(--accent)}
  html[data-file] .doc ol.passes:has(li:hover) li:not(:hover){color:var(--text-3)}
  /* the HUD notes' figures take the accent while the hand is on the figure */
  html[data-file] .doc .hud .hudnote b{transition:color var(--snap)}
  html[data-file] .doc .hud:hover .hudnote b{color:var(--accent-text)}
  /* a see-also card lifts a hair */
  html[data-file] .doc aside.seealso a{transition:translate var(--snap)}
  html[data-file] .doc aside.seealso a:hover{translate:0 -2px}
  /* the checks and the decisions: the pointed one keeps its ink */
  html[data-file] .doc .checks .check,html[data-file] .doc .decisions .decision{transition:color var(--snap)}
  html[data-file] .doc .checks:has(.check:hover) .check:not(:hover){color:var(--text-3)}
  html[data-file] .doc .decisions:has(.decision:hover) .decision:not(:hover){color:var(--text-3)}
}
/* the keyboard twins */
html[data-file] .doc .handnote:focus-within{border-left-color:var(--accent)}
html[data-file] .doc ol.passes li:focus-within{border-top-color:var(--accent)}
html[data-file] .doc aside.seealso a:focus-visible{translate:0 -2px}
html[data-file] .doc aside.seealso a:focus-visible b{color:var(--accent-text)}
/* the chain bars fill as the scroll brings them in, one after another */
@media(prefers-reduced-motion:no-preference){
  @supports (animation-timeline: view()){
    html[data-file] .doc ol.chainbars li::after{transform-origin:0 50%;animation:bar-fill linear both;animation-timeline:view();animation-range:entry 0% entry 80%}
  }
}
@keyframes bar-fill{from{transform:scaleX(0)}}
