#lit-list{padding:clamp(96px,11vw,168px) 0}
/* S2 item 5: equal side gutters, same token the rest of the page uses (var(--gut), the exact
   pattern .wrap.w already applies for a section wider than the standard --max column) -- the
   old min(100% - 48px,1400px) was a flat 24px-a-side margin, narrower and a different edge than
   every sibling section's own --gut, so the page read unevenly gutter-to-gutter at wide widths.
   The max-width is this section's own (wider than --wide: at 961px+ the scene and the 28% word
   column need more room than the sitewide 1520px cap allows to reach their target sizes). */
#lit-list .lit-list-inner{width:100%;max-width:1676px;margin-inline:auto;padding:0 var(--gut);box-sizing:border-box}
/* POLISH-NOTES item 16, continued: this margin (up to 116px at 1512)
   was a SECOND gap stacking on top of .lit-list-words' own top padding
   below -- 116 + 96 = 212px between the lead and the first word, most
   of the "starts below the fold" complaint. .lit-list-words' own 96px
   token already gives the list its breathing room, so this only needs
   to be a small buffer under the lead paragraph itself, not a second
   section-sized gap. */
#lit-list .lit-list-head{max-width:880px;margin-bottom:40px}
#lit-list .lit-list-kicker{margin:0 0 24px;color:var(--accent);font:400 12px/1.4 var(--mono);letter-spacing:.04em}
#lit-list .lit-list-intro{margin:0;color:var(--ink-2);font:400 clamp(22px,2.25vw,32px)/1.3 var(--sans);letter-spacing:-.02em}
#lit-list .lit-list-intro span{color:var(--ink)}
#lit-list .lit-list-layout{display:grid;grid-template-columns:minmax(340px,.68fr) minmax(660px,1.5fr);gap:clamp(40px,4.5vw,72px);align-items:start}
/* POLISH-NOTES item 16: 14vh (126px at 900px tall, more on a taller
   screen -- this unit grows with viewport height, which is why it read
   as excessive rather than a fixed, deliberate amount) put the list's
   own first word about 240px below the lead paragraph, well past a
   comfortable reading continuation -- the list started below the fold.
   Swapped for --sec-sm, the same flat rhythm token the rest of the page
   already uses for section spacing, so the list picks up right where
   the lead leaves off instead of floating in its own gap. The bottom
   38vh is untouched -- that's the scroll runway the sticky scene on the
   right needs to cycle through all six disciplines, not dead space. */
#lit-list .lit-list-words{display:flex;flex-direction:column;padding:var(--sec-sm) 0 38vh}
#lit-list .lit-list-word{display:block;color:var(--ink-3);font:500 clamp(56px,5vw,72px)/1.24 var(--sans);letter-spacing:-.04em;text-decoration:none;transition:color .3s ease}
#lit-list .lit-list-word.is-active{color:var(--ink)}
#lit-list .lit-list-scenes{position:sticky;top:max(88px,9vh);height:min(680px,82vh)}
#lit-list .lit-scene{position:absolute;inset:0;display:flex;flex-direction:column;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .3s ease,visibility 0s linear .3s}
#lit-list .lit-scene.is-active{visibility:visible;opacity:1;pointer-events:auto;transition:opacity .3s ease}
#lit-list .lit-flow{position:relative;flex:none;min-width:0;height:min(580px,70vh);min-height:480px;overflow:hidden;background:var(--glass-bg)}
#lit-list .lit-node{position:absolute;z-index:2;border:1px solid var(--glass-line);background:var(--bg-3);min-width:0}
#lit-list .lit-node img,#lit-list .lit-node video{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 50%}
#lit-list .lit-backdrop{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.18;pointer-events:none}
#lit-list .lit-backdrop-scrim{position:absolute;inset:0;background:linear-gradient(90deg,rgba(0,0,0,.35),rgba(0,0,0,.65) 50%,rgba(0,0,0,.35));pointer-events:none}
#lit-list .lit-input{left:3%;top:29%;width:24%;height:42%}
#lit-list .lit-input .node-bar{display:block}
#lit-list .lit-lens{left:36%;top:34%;width:20%;height:32%;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:16px;padding:14px 10px}
#lit-list .lit-lens .node-bar{position:static;display:block;padding:0;width:100%}
#lit-list .lit-node .node-source{display:block;margin-top:5px;text-align:left;white-space:normal;color:var(--ink-2);font:400 10px/1.45 var(--mono);overflow-wrap:anywhere}
#lit-list .lit-node .node-title{font:500 11px/1.4 var(--mono);letter-spacing:.02em}
#lit-list .lit-output{right:3%;width:32%;height:28%;display:flex;flex-direction:column}
#lit-list .lit-output[data-lit-output="1"]{top:4%}
#lit-list .lit-output[data-lit-output="2"]{top:36%}
#lit-list .lit-output[data-lit-output="3"]{top:68%}
#lit-list .lit-output img,#lit-list .lit-output video{flex:1;min-height:0;height:0}
#lit-list .lit-output .node-bar{position:static;display:block;flex:none;padding:9px 11px;background:var(--bg-2)}
#lit-list .lit-aperture{width:42px;flex:none;aspect-ratio:1;border:1px solid var(--accent);border-radius:50%;box-shadow:inset 0 0 0 10px var(--bg-2),inset 0 0 0 11px var(--line-raised)}
#lit-list .connector{z-index:1}
#lit-list .connector path{fill:none;stroke:var(--line-raised);stroke-width:1;vector-effect:non-scaling-stroke;stroke-dasharray:1;stroke-dashoffset:0}
#lit-list .connector path.is-live{stroke:var(--accent)}
#lit-list .lit-scene h3{margin:24px 0 0;color:var(--ink);font:500 24px/1.2 var(--sans);letter-spacing:-.02em}
#lit-list .lit-scene>p{max-width:680px;margin:8px 0 0;color:var(--ink-2);font:400 15px/1.55 var(--sans);letter-spacing:.02em}
@media(max-width:960px){#lit-list .lit-list-layout{grid-template-columns:1fr}#lit-list .lit-list-words{position:sticky;z-index:8;top:0;flex-direction:row;gap:24px;overflow-x:auto;padding:0;background:var(--bg);scrollbar-width:none}#lit-list .lit-list-words::-webkit-scrollbar{display:none}
  /* Job 23 mobile audit: the strip was a 12px-tall line of mono text with
     no padding of its own -- a real tap target smaller than any other
     control on the page, and nothing signalled there were six words to
     scroll to, not just however many fit the first screen. flex/min-height
     centering gives every word the same 44px target regardless of its own
     text metrics; the fade is a real edge mask (mask-image, not a solid
     overlay, so it works on the room's own dotted-grid canvas background
     too), only at the trailing edge -- the strip starts scrolled to its own
     left, so a leading fade would suggest content that isn't there yet. */
  #lit-list .lit-list-words{display:flex;align-items:stretch;-webkit-mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 28px),transparent 100%)}
  #lit-list .lit-list-word{flex:none;display:flex;align-items:center;min-height:44px;font:400 12px/1 var(--mono);letter-spacing:.04em}
#lit-list .lit-list-scenes{position:relative;top:auto;height:auto}#lit-list .lit-scene,#lit-list .lit-scene.is-active{position:relative;inset:auto;visibility:visible;opacity:1;pointer-events:auto;margin-bottom:64px}#lit-list .lit-flow{height:580px}
  /* Job N6 item 5a: every scene is visible and stacked at this width (the
     rule above), but the DOM order is flow-then-h3 (the desktop word nav
     is the label there, so the h3 only needs to exist, not lead) -- on
     the stacked mobile layout that puts "Photography" directly above the
     BRAND scene's own flow, reading as its label. order:-1 moves the
     heading before the flow within this flex column, scoped to this
     breakpoint only (desktop's own absolute-stacked scenes are
     untouched, since order only visibly matters once .lit-scene is
     actually in normal flex flow, which only happens here). */
  #lit-list .lit-scene h3{order:-1;margin:0 0 20px}
}
@media(max-width:600px){
  #lit-list{padding:80px 0}
  #lit-list .lit-list-inner{width:min(100% - 32px,480px)}
  #lit-list .lit-list-head{margin-bottom:48px}
  #lit-list .lit-list-layout{gap:28px}
  #lit-list .lit-scene{scroll-margin-top:64px}
  /* Job N6 item 5b: input, lens and three outputs used to stack full-
     width, one per grid row -- about 1,300px per scene (measured: 210
     input + 132 lens + 3x232 outputs + 4x32 gaps + 48 padding). Compact
     layout instead: input spans the full width in row 1; the lens node
     shares that SAME grid cell (grid-row/grid-column both set to row 1,
     matching input's own placement) instead of getting its own row,
     align-self/justify-self pulling it to the input's own bottom centre
     so it overlays there rather than following as a separate block --
     it paints on top by DOM order alone (it comes after input in the
     markup, no z-index needed for two items sharing one grid cell). The
     three outputs go in row 2 as a real 3-up (grid's own natural auto-
     placement across 3 columns, no per-item rule needed). Height per
     scene: ~210 (input+overlaid lens) + ~180 (outputs, now square-ish
     instead of 232px tall full-width cards) + gaps/padding, under the
     ~750px target. Left padding evened out from 38 to 22 now that the
     connector spine it made room for is hidden below. */
  #lit-list .lit-flow{height:auto;min-height:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 10px;padding:18px 22px}
  #lit-list .lit-node{position:relative;inset:auto!important;width:100%;height:auto}
  #lit-list .lit-input{grid-column:1/-1;grid-row:1;height:210px}
  /* the lens sits under the input frame, full width, so the photo shows whole; a short vertical spine joins them */
  #lit-list .lit-lens{grid-column:1/-1;grid-row:2;width:100%;min-height:0;margin:0;flex-direction:row;justify-content:space-between;align-items:center;padding:10px 14px;gap:12px}
  #lit-list .lit-lens::before{content:"";position:absolute;left:50%;top:-12px;height:12px;width:1px;background:var(--accent)}
  #lit-list .lit-lens .node-bar{width:auto}
  #lit-list .lit-lens .lit-aperture{width:30px}
  #lit-list .lit-output{grid-row:3;height:150px}
  #lit-list .lit-output .node-bar{padding:9px}
  #lit-list .lit-node .node-source{font-size:10px}
  #lit-list .lit-node .node-title{font-size:11px}
  /* connectors hidden on the stacked layout, per the note -- the input-
     to-lens-to-outputs relationship now reads from the overlay and the
     3-up row directly, not from drawn lines that no longer map to
     anything (the paths were computed for the old one-column stack). */
  #lit-list .connector{display:none}
}
@media(prefers-reduced-motion:reduce){#lit-list .lit-list-word{transition:none}#lit-list .lit-scene{transition:none}#lit-list .connector path{stroke-dashoffset:0!important}}

#lit-list .lit-list-word:focus-visible{outline:1px solid var(--ink);outline-offset:4px}


/* ═════════ D3 · THE USE-CASE LIST PACES AND SHOWS THE WORK (desktop, 961px and up) ═════════
   Pacing: the layout is 3.6 viewports tall (0.6 of a viewport per discipline; 0.7 on a phone) (plus the scene) and the word list and the scene are
   sticky inside it, so every discipline holds one full viewport of scroll; lit-list.js switches
   on progress and snaps to each discipline's centre. The word list is one stationary column, so
   it can never sit mid-word. The switch is a cut: the outgoing scene is gone at once and the
   incoming one settles in over 200ms.
   Cards: the scene grows to 720px and the frames are sized so at least 70% of each image's
   height shows at 1512 (an input in a 3:4 card, outputs in near-square cards whose caption
   is two one-line rows). */
@media(min-width:961px){
  /* S2 item 5: the sticky viewport centres its contents, top and bottom margins equal. --lit-navh
     approximates the fixed nav's own clearance (the same max(88px,9vh) hero.js and lit-list.js
     already use); the visible band below it runs from --lit-navh to 100vh, and its own centre is
     50vh + --lit-navh/2. --lit-h keeps a height ceiling from the viewport itself (100vh - 200px) so
     a short browser window never forces the centred box taller than the room around it.
     S7: `top` is that centre line MINUS half the box's own height, baked in directly (a max()
     floor at --lit-navh so a very short viewport never sticks the box up under the fixed nav) --
     not the centre line itself with a translateY(-50%) shift on top, which was the bug (Ittai's
     screenshot, S2 to S7): position:sticky's own "is it stuck yet" test compares the element's
     NATURAL in-flow position against `top`, and only ONCE the page has scrolled the section into
     that zone does `top` become the rendered position -- but `transform` is not part of that test
     and paints on EVERY frame regardless, stuck or not. Before the section had scrolled anywhere
     near the sticky zone (both columns still sitting in normal flow below the intro, well down the
     page), the -50% shift was already lifting them by half their own height (408px at 1512), which
     is more than enough to paint over #one-lens above and the section's own intro copy. Computing
     the exact target top directly removes the transform, so the UNSTUCK render is just the
     ordinary, correct in-flow position (right after .lit-list-head, inside #lit-list, nothing
     above it) and the STUCK render lands at the identical centred pixel S2 measured (127 at 1512,
     151 at 1920 -- unchanged). */
  #lit-list{--lit-navh:max(88px,9vh);--lit-h:clamp(600px,min(14.71vw + 498px,calc(100vh - 200px)),780px);--lit-box-h:calc(var(--lit-h) + 96px);--lit-top:max(var(--lit-navh),calc(50vh + var(--lit-navh)/2 - var(--lit-box-h)/2))}
  #lit-list .lit-list-layout{height:calc(360vh + var(--lit-h) + 120px);align-items:start;grid-template-columns:minmax(280px,28%) minmax(0,1fr)}
  #lit-list .lit-list-words{position:sticky;top:var(--lit-top);height:var(--lit-box-h);justify-content:center;padding:0}
  #lit-list .lit-list-scenes{width:100%;max-width:1060px;height:var(--lit-box-h);top:var(--lit-top)}
  #lit-list .lit-flow{width:100%;height:var(--lit-h);min-height:0}
  #lit-list .lit-scene{transition:none}
  #lit-list .lit-scene.is-active{transition:none;animation:litSettle .2s ease-out both}
  /* the input and the lens sit on a top row, the three outputs on a bottom row of tall cards (a picture
     area close to 3:4, so most of every image shows) with their captions under them */
  #lit-list .lit-input{left:3%;top:2.5%;height:38.5%;width:auto;aspect-ratio:.75}
  #lit-list .lit-lens{left:40%;top:8%;width:22%;height:28%}
  #lit-list .lit-output{bottom:1.5%;top:auto!important;height:55%;width:29%}
  #lit-list .lit-output[data-lit-output="1"]{left:3%}
  #lit-list .lit-output[data-lit-output="2"]{left:35.25%}
  #lit-list .lit-output[data-lit-output="3"]{left:67.5%}
  /* a video card takes the video's own aspect (9:16 files): the picture area is the frame, no black around it */
  #lit-list .lit-output:has(video){width:auto;aspect-ratio:auto;left:auto!important;right:3%}
  /* a series with two frames shows two outputs, centred under the lens */
  #lit-list [data-lit-scene="editorial"] .lit-output[data-lit-output="1"]{left:19.1%}
  #lit-list [data-lit-scene="editorial"] .lit-output[data-lit-output="2"]{left:51.4%}
  #lit-list [data-lit-scene="brand"] .lit-output[data-lit-output="1"]{left:19.1%}
  #lit-list [data-lit-scene="brand"] .lit-output[data-lit-output="2"]{left:51.4%}
  /* Brand is a campaign previz: the line-up comes in at the left, the two material references feed the lens from the
     right, and two mockups of the line-up on those materials come out */
  #lit-list [data-lit-scene="brand"] .lit-lens{left:33%;width:22%}
  #lit-list .lit-material{top:5%;height:26%;width:auto;aspect-ratio:.8}
  #lit-list .lit-material[data-lit-material="1"]{left:61.5%}
  #lit-list .lit-material[data-lit-material="2"]{left:79.5%}
  /* the video keeps its own file's aspect (data-native-aspect, 360:640 from LIBRARY.json), object-fit contain: the card is
     exactly as wide as the video is at the height left over under the caption, never a crop */
  #lit-list .lit-output video[data-native-aspect]{flex:none;width:auto;height:calc(100% - 96px);object-fit:contain;background:#050505;align-self:center}
  /* S8 item 3 (Fable's own fresh-eyes walk at 1920): S2 item 6's own
     measurement said ellipsis "clears it entirely at 1920" -- it didn't;
     the four-part sources (SKILL.md · LIVE · Illustrative and similar)
     were still truncating mid-word (Illustrati…, LIVE · Il…, SKILL.md ·
     LIVE · Il…) on every discipline at that width. node-source is one
     text string per card (index.html), not separate spans per token, so
     dropping just the third token isn't reachable from this file alone
     without a markup change -- wrapping is. Two lines, hard-capped
     (-webkit-line-clamp, broadly supported despite the -webkit- prefix,
     not just Safari) rather than open-ended wrapping, so a run of real
     bad luck (a longer source on a narrower card) still can't grow a
     caption into a third line and crowd the picture -- the exact
     failure S2 item 6 was originally guarding against, just solved by
     capping the wrap instead of clipping the text. No text-overflow:
     ellipsis paired with the clamp -- Fable's own instruction is no
     ellipsis at all; on the rare case content still doesn't fit two
     lines, it hard-clips with no "…", not a third failure mode to chase
     here. The full text is still on the element's own text content
     either way, unaffected by the visual wrap. */
  #lit-list .lit-node .node-title,#lit-list .lit-node .node-source{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;white-space:normal;max-width:100%}
  #lit-list .lit-output .node-bar{padding:6px 10px}
  #lit-list .lit-output .node-source{margin-top:2px}
  #lit-list .lit-lens{padding:14px 12px}
}
@keyframes litSettle{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* D3 at every width: a phone gets the same pacing. The word strip sticks under the fixed nav, the scene
   sticks under it, only the active scene shows, and the layout is 3.6 viewports tall (0.6 of a viewport per discipline; 0.7 on a phone) so each discipline
   holds one full viewport of scroll (lit-list.js snaps to the centres). */
@media(max-width:960px){
  #lit-list{--lit-h:min(700px,calc(100vh - 190px))}
  #lit-list .lit-list-layout{height:calc(420vh + var(--lit-h) + 110px);gap:28px}
  /* both sticky blocks share the layout's one tall row (a grid would otherwise stretch its rows): the strip on
     top, the scene 72px below it, and each stays put for the whole six viewports */
  #lit-list .lit-list-layout{grid-template-rows:1fr}
  #lit-list .lit-list-words{top:62px;grid-area:1/1;align-self:start}
  #lit-list .lit-list-scenes{position:sticky;top:134px;height:var(--lit-h);grid-area:1/1;align-self:start;margin-top:72px}
  #lit-list .lit-scene{position:absolute;inset:0;visibility:hidden;opacity:0;pointer-events:none;margin-bottom:0;transition:none}
  #lit-list .lit-scene.is-active{visibility:visible;opacity:1;pointer-events:auto;animation:litSettle .2s ease-out both}
}

@media(max-width:600px){
  /* the three outputs read as square pictures with their captions under them (the captions may wrap, they never
     take the picture's space), and the input gets more height */
  #lit-list{--lit-h:calc(100vh - 134px)}
  /* the input frame takes its image's own aspect (the img's width and height), centred, 46% wide */
  #lit-list .lit-input{grid-column:1/-1;justify-self:center;width:46%;height:auto}
  #lit-list .lit-input img{height:auto}
  #lit-list .lit-output{height:auto}
  #lit-list .lit-output img{flex:none;height:auto;width:100%;aspect-ratio:1;object-fit:cover}
  #lit-list .lit-output video[data-native-aspect]{flex:none;width:100%;height:auto;object-fit:contain}
  #lit-list .lit-output .node-bar{padding:6px 7px}
  #lit-list .lit-node .node-source{font-size:9px;letter-spacing:0}
  #lit-list .lit-node .node-title,#lit-list .lit-node .node-source{overflow-wrap:normal}
  /* Job P1 item 7: v3.css's own #lit-list .lit-node.lit-output .node-source
     rule (three classes, out-specifies this file's two-class selectors)
     holds the output captions at font:var(--t-1) (12px) regardless of
     this block's own 9px attempt above, and the longest one ("Midjourney
     · Style prompt · LIVE · Illustrative") doesn't fit its own 81px
     column at that size even wrapping at spaces -- "Illustrative" alone
     is wider than the column. overflow-wrap:normal (the line above) is
     the deliberate general policy at this width (no ugly mid-word
     breaks); restored to anywhere for output captions specifically,
     where it's this or a real clip -- measured clean after, 0px over. */
  #lit-list .lit-output .node-source{overflow-wrap:anywhere}
}

@media(min-width:601px) and (max-width:960px){#lit-list .lit-material{display:none}}
#lit-list .lit-material .node-source{display:none}
@media(max-width:600px){
  #lit-list [data-lit-scene="brand"] .lit-flow{grid-template-columns:repeat(4,minmax(0,1fr))}
  #lit-list .lit-material{grid-row:3;grid-column:span 2;height:auto;width:100%}
  #lit-list .lit-material img{aspect-ratio:3;height:auto}
  #lit-list [data-lit-scene="brand"] .lit-output{grid-column:span 2;grid-row:4}
  #lit-list [data-lit-scene="brand"] .lit-output img{aspect-ratio:1.25}
}
