@font-face{font-family:'Jost';font-style:normal;font-weight:300;font-display:swap;src:url(/src/fonts/jost-300-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Jost';font-style:normal;font-weight:300;font-display:swap;src:url(/src/fonts/jost-300-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Jost';font-style:normal;font-weight:400;font-display:swap;src:url(/src/fonts/jost-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Jost';font-style:normal;font-weight:400;font-display:swap;src:url(/src/fonts/jost-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Jost';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/jost-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Jost';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/jost-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Jost';font-style:normal;font-weight:600;font-display:swap;src:url(/src/fonts/jost-600-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Jost';font-style:normal;font-weight:600;font-display:swap;src:url(/src/fonts/jost-600-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Karla';font-style:normal;font-weight:300;font-display:swap;src:url(/src/fonts/karla-300-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Karla';font-style:normal;font-weight:300;font-display:swap;src:url(/src/fonts/karla-300-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Karla';font-style:normal;font-weight:400;font-display:swap;src:url(/src/fonts/karla-400-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Karla';font-style:normal;font-weight:400;font-display:swap;src:url(/src/fonts/karla-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Karla';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/karla-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Karla';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/karla-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/space-grotesk-500-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(/src/fonts/space-grotesk-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(/src/fonts/space-grotesk-700-latin-ext.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(/src/fonts/space-grotesk-700-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:"Source Serif 4"; font-style:normal; font-weight:600; font-display:swap;
  src:url("/src/fonts/sourceserif-600-latin-ext.woff2") format("woff2"); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"Source Serif 4"; font-style:normal; font-weight:600; font-display:swap;
  src:url("/src/fonts/sourceserif-600-latin.woff2") format("woff2"); unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:"Source Serif 4"; font-style:normal; font-weight:700; font-display:swap;
  src:url("/src/fonts/sourceserif-700-latin-ext.woff2") format("woff2"); unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"Source Serif 4"; font-style:normal; font-weight:700; font-display:swap;
  src:url("/src/fonts/sourceserif-700-latin.woff2") format("woff2"); unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

/**
 * DISCOVERFILMS.US. One page, one wall, four filters and a search box.
 *
 * THE PALETTE AND THE CARD ARE CARRIED OVER WHOLE from the site this grew out
 * of, because the thing being reused is the part that was already right: a
 * near-black ground cut from one cool hue, warm off-white ink, one accent, and
 * a card that is a 16:9 still with a play control centred on it. Every value
 * below is a token, so the wall inverts by editing this block and nothing else.
 *
 * WHY A DARK GROUND HERE AND NOT THERE. The site this came from argued itself
 * onto a light ground because a wall of covers on black reads as a streaming
 * grid. This *is* a streaming grid. It is twelve thousand film stills and
 * nothing else, and the one thing it must do is get out of their way.
 */
:root{
  color-scheme:dark;
  --paper:#0d0f12; --paper-top:#08090b; --raised:#16191e; --sunk:#0a0c0f;
  --stripe:#131619; --footer-glow:#23262a;
  --ink:#e9e6e0; --ink2:#b0aca5; --ink3:#a4a09a;
  --title-ink:#f7f5f1; --rule:#33383f; --hair:#23272d;
  --ctl:#171a1f; --ctl-line:#2e333a; --ctl-ink:#a8a49d;
  --ctl-hover:#1e2228; --ctl-hover-line:#4a5058; --ctl-hover-ink:#f7f5f1;
  --accent:#e9b949; --accent-soft:#241c0d; --accent-line:#6b5424;
  --bar-ground:#050607;
  --measure:110rem;
  --head:"Space Grotesk","Avenir Next",Corbel,system-ui,sans-serif;
  --text:"Karla","Avenir Next",Corbel,system-ui,sans-serif;
  --meta:"Jost","Avenir Next",Corbel,system-ui,sans-serif;
  --display:"Source Serif 4",Georgia,"Times New Roman",serif;
}
*,*::before,*::after{box-sizing:border-box}
html{font-size:17px; scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){ html{scroll-behavior:auto} }
body{margin:0; background:var(--paper); color:var(--ink);
  font:1.02rem/1.72 var(--text); text-rendering:optimizeLegibility}
.wrap{max-width:var(--measure); margin:0 auto; padding:0 clamp(1.1rem,2.4vw,2.2rem)}

.skip{position:absolute; left:-999px; top:0; z-index:20;
  background:var(--ctl); color:var(--ink); padding:.7rem 1rem; border:1px solid var(--accent)}
.skip:focus{left:.6rem; top:.6rem}

/* THE MASTHEAD. The name on the left, the search box on the right, and the
   filters on their own rows under both. It sticks, because a reader forty
   frames down the wall who wants a different decade should not have to go
   back up to find one. */
header.top{position:sticky; top:0; z-index:10;
  background:var(--bar-ground); border-bottom:1px solid var(--rule)}
.topin{display:flex; align-items:center; gap:.7rem 1.6rem; flex-wrap:wrap;
  padding-top:.75rem; padding-bottom:.55rem}
.brand{display:block; font-family:var(--head); font-weight:700;
  font-size:1.42rem; letter-spacing:-.022em; line-height:1.15;
  color:var(--title-ink); text-decoration:none; white-space:nowrap}
.brand:hover{color:var(--accent)}
.brand .dot{color:var(--accent)}
@media (max-width:44rem){ .brand{font-size:1.16rem} }

/* THE COUNT IS THE ONLY NUMBER ON THE PAGE and it moves as the filters move,
   which is the whole feedback a reader gets that a filter did anything. */
.count{margin:0; order:2; font-family:var(--meta); font-size:.7rem; font-weight:600;
  letter-spacing:.13em; text-transform:uppercase; color:var(--ink3);
  white-space:nowrap}
.count b{color:var(--accent); font-weight:600}

/* THE SEARCH BOX TAKES THE FAR EDGE, where the line about the site used to
   sit on the site this came from. It is the one control here that is not a
   filter row, so it is the one control that does not look like one. */
.find{order:2; margin-left:auto; display:flex; align-items:center; gap:.5rem;
  flex:1 1 16rem; max-width:24rem; min-width:11rem;
  background:var(--ctl); border:1px solid var(--ctl-line); border-radius:2px;
  padding:.36rem .6rem; transition:border-color .12s ease}
.find:focus-within{border-color:var(--accent)}
.find svg{flex:none; color:var(--ink3)}
.find input{flex:1 1 auto; min-width:0; background:none; border:0; outline:0;
  color:var(--ink); font:.82rem/1.4 var(--text)}
.find input::placeholder{color:var(--ink3)}
.find button{flex:none; display:none; background:none; border:0; cursor:pointer;
  color:var(--ink3); font-size:1rem; line-height:1; padding:0 .1rem}
.find button:hover{color:var(--accent)}
.find.on button{display:block}


/* THE ONE PAGE THAT IS NOT THE WALL, which is the miss. It was also the empty
   state of three sections that no longer exist: Music, Comedy and Books came
   down on 16 September 2026, at his word, the day after they went up. This
   site is films. */
.state{max-width:34rem; margin:6rem auto; padding:0 1.4rem; text-align:center}
.state h1{margin:0 0 .6rem; font-family:var(--display); font-weight:700;
  font-size:2rem; letter-spacing:-.02em; color:var(--title-ink)}
.state p{margin:0 0 .8rem; color:var(--ink2); font-size:1rem; line-height:1.6}
.state .statenote{font-family:var(--meta); font-size:.7rem; font-weight:600;
  letter-spacing:.11em; text-transform:uppercase; color:var(--accent);
  line-height:1.7}


/* THE FILTER ROWS, AND EACH ONE IS A LINE THAT SCROLLS SIDEWAYS.
   Eleven decades, eighteen genres and fifty-two studios is eighty-one items.
   Wrapped, that is a five-line block of capitals pushing the first film below
   the fold on every screen; on one line each it costs three rows of about a
   centimetre and the wall starts where it should.
   THE LABEL SITS OUTSIDE THE SCROLLER. With three rows stacked, a row that
   scrolls away from its own name is a row you cannot identify, and the label
   is the one thing on it that must never move. */
.filters{border-top:1px solid var(--hair)}
.frow{display:flex; align-items:center; gap:0 1rem; padding:.3rem 0}
.frow + .frow{border-top:1px solid var(--hair)}
.flabel{flex:none; width:4.6rem; margin:0; font-family:var(--meta); font-weight:600;
  font-size:.62rem; letter-spacing:.14em; text-transform:uppercase; color:var(--ink3)}
@media (max-width:44rem){ .flabel{width:3.4rem; font-size:.56rem; letter-spacing:.1em} }

/* THE ROW ITSELF, carried over from the topic bar it is modelled on: hidden
   scrollbar, and a mask that fades whichever edge has more behind it. The
   fade is drawn from the scroll position rather than painted on permanently,
   so at the far right there is no false promise of more. Without the script
   it is the right-hand fade and no left one, which is the state a reader
   lands in: scrolled to the start, with more to the right. */
.views{display:flex; flex-wrap:nowrap; gap:0 1.15rem; margin:0; padding:.22rem 0;
  flex:1 1 auto; min-width:0; max-width:none;
  overflow-x:auto; overscroll-behavior-x:contain;
  scrollbar-width:none; -ms-overflow-style:none;
  --fadel:0px; --fader:2.6rem;
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 var(--fadel),
    #000 calc(100% - var(--fader)), transparent 100%);
  mask-image:linear-gradient(to right, transparent 0, #000 var(--fadel),
    #000 calc(100% - var(--fader)), transparent 100%)}
.views::-webkit-scrollbar{display:none}
.views.scrolled{--fadel:2.6rem}
.views.atend{--fader:0px}
.views > .view{flex:none; white-space:nowrap}

.view{font-family:var(--meta); font-weight:600; font-size:.72rem;
  letter-spacing:.13em; text-transform:uppercase; color:var(--ink3);
  text-decoration:none; white-space:nowrap; padding:.18rem 0 .2rem;
  border:0; border-bottom:1px solid transparent; background:none; cursor:pointer}
/* A DECADE IS 1970s AND NOT 1970S, at his word, 17 September 2026. Every label
   in this bar is set in tracked capitals, and text-transform took the s of a
   decade with it: the row read 2020S 2010S 1990S, which is not how anybody
   writes a decade. The transform comes off this row and the decades are typed
   the way they are read. Its own All is typed in capitals in the markup
   instead, so the word still matches the All on every other row. */
.views[data-kind="decade"] .view{text-transform:none; letter-spacing:.1em}
.view:hover{color:var(--ink)}
.view.here{color:var(--ink); border-bottom-color:var(--accent)}
/* A TIER HEADING INSIDE THE STUDIO ROW. Fifty-two studios in one alphabetical
   run tells a reader nothing about which of them is Warner Bros. and which is
   Zeitgeist. The three words are not controls and do not take a pointer. */
.vgroup{flex:none; align-self:center; font-family:var(--meta); font-weight:600;
  font-size:.58rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent); opacity:.75; white-space:nowrap;
  padding-left:.3rem; border-left:1px solid var(--rule)}
.frow:first-child .vgroup{border-left:0; padding-left:0}

/* THE YEAR ROW IS NOT THERE UNTIL A DECADE IS. Ten more items on the page at
   all times, nine of which are wrong for whatever the reader is looking at,
   is the row that makes the other three harder to read. */
.frow.years[hidden]{display:none}

/* THE WALL REACHES EVERY EDGE, 17 September 2026, at his word, on America,
   America's model. It had the page's own gutter down each side and a measure
   capping it at 110rem, which is right for a column of words and wrong for a
   wall of pictures: a grid of stills inside a margin reads as a panel of
   images placed on a page, and the same grid running off all four sides reads
   as the page. The masthead and the foot keep their gutter, because those are
   words.
   THE RULE IS ON main AND NOT ON .wall so the state and the empty message
   inherit it, and each carries its own padding back. */
main{width:100%; max-width:none; margin:0; padding:0}

/* THE WALL. Two across on a phone, and up from there by the width of a card
   rather than by a breakpoint somebody chose: auto-fill with a minimum keeps
   a still from ever being stretched past the size its own detail survives. */
.wall{display:grid; gap:1.9rem 1.2rem; margin:0; padding:0;
  list-style:none; grid-template-columns:repeat(auto-fill,minmax(15rem,1fr))}
@media (max-width:40rem){ .wall{gap:1.4rem .9rem;
  grid-template-columns:repeat(auto-fill,minmax(9.5rem,1fr))} }


/* THE TWO WAYS THE WALL IS DRAWN, and the control is two icons because the
   thing being chosen is a shape. A word would have to be "Grid" and "Tiles",
   which are names for what you get rather than pictures of it, and the picture
   is exactly what differs: boxes with air between them, or a square in
   quarters with none. */
.vtoggle{order:2; display:flex; flex:none; gap:0 .55rem}
/* NO BOX, 17 September 2026, at his word. It was a bordered pill with a
   divider down the middle and a filled ground on the chosen half, which is the
   shape every other control on this site uses and the wrong one here: the
   masthead already carries a bordered box, the search, and two of them side by
   side read as two inputs. The icons are the control now and state is carried
   by ink alone, which is what the filter rows beside them do.
   THE FOCUS RING STAYS, and it is the one ring that cannot go. Without a box
   and without a ground, a keyboard has nothing at all to show it is here. It
   is drawn only for a keyboard, which is what focus-visible means. */
.vt{display:flex; align-items:center; justify-content:center;
  width:1.4rem; height:1.4rem; padding:0; border:0; background:none;
  cursor:pointer; color:var(--ink3); transition:color .12s ease}
@media (prefers-reduced-motion:reduce){ .vt{transition:none} }
.vt:hover{color:var(--ink)}
.vt.on{color:var(--accent)}
.vt:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:1px}

/* THE ONE THING IN THE BAR THAT IS NOT A FILTER OF THE WORK BUT A FILTER OF
   THE RECORD. Every other control asks what a reader wants to see; this one
   asks whether to show films this site knows about and cannot play. It is a
   checkbox because it is a yes or no about the whole wall rather than a choice
   among values, and it is checked to begin with because a wall of grey plates
   is the wrong first impression of a site made of pictures. */
.onlyplay{order:2; display:flex; align-items:center; gap:.4rem; flex:none;
  cursor:pointer; font-family:var(--meta); font-weight:600; font-size:.64rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink3);
  white-space:nowrap; user-select:none}
.onlyplay:hover{color:var(--ink)}
.onlyplay input{appearance:none; width:.85rem; height:.85rem; margin:0;
  border:1px solid var(--ctl-line); border-radius:2px; background:var(--ctl);
  cursor:pointer; position:relative; flex:none}
.onlyplay input:checked{background:var(--accent); border-color:var(--accent)}
/* THE TICK IS DRAWN AND NOT SET IN TYPE, so it lands on the same two pixels in
   every browser and does not move with the font. */
.onlyplay input:checked::after{content:""; position:absolute; left:.24rem; top:.06rem;
  width:.22rem; height:.45rem; border:solid var(--sunk);
  border-width:0 2px 2px 0; transform:rotate(42deg)}
.onlyplay input:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
.onlyplay:has(input:checked){color:var(--ink)}
@media (max-width:52rem){ .onlyplay span{display:none} }

/* THE HOVER BAR. Last row of the sticky masthead, so the words about a tile
   four thousand rows down still appear somewhere the reader is looking. It
   holds its height empty, because a bar that appears on hover would push the
   entire wall down a line every time the pointer crossed a picture. */
/* A FIXED HEIGHT, AND IT HAS TO BE FIXED RATHER THAN MINIMUM.
   WHAT HE SAW: hovering the first row of tiles, right against the bar, made
   the page shutter. It was a feedback loop and the bar was driving it. Idle it
   holds one line of eleven-pixel capitals and was clamped to its 2.1rem
   minimum; hovering put a one-rem serif title in it, which at the body's line
   height wants 2.47rem, so the bar grew by six pixels and pushed the whole wall
   down. The pointer, which had been on the first tile, was now over the bar
   instead. That un-hovered the tile, the bar went back to idle, the wall came
   back up, the tile was under the pointer again, and it hovered. Sixty times a
   second.
   THE FIX IS THAT NEITHER STATE MAY CHANGE THE HEIGHT. One fixed height,
   centred rather than aligned to a baseline that moves with the font, and
   explicit line heights on both children so a longer title or a different face
   cannot reach past it. min-height was the bug: it promises a floor and says
   nothing about a ceiling, which is exactly the wrong half of the guarantee
   for anything sitting above a wall that must not move. */
.hoverbar{display:flex; align-items:center; gap:0 .9rem;
  height:2.5rem; padding:0;
  border-top:1px solid var(--hair); overflow:hidden; white-space:nowrap}
.hoverbar[hidden]{display:none}
.hbtitle{margin:0; font-family:var(--display); font-weight:600; font-size:1rem;
  line-height:1.2; color:var(--title-ink); overflow:hidden; text-overflow:ellipsis}
.hbmeta{margin:0; flex:none; font-family:var(--meta); font-weight:600; line-height:1.2;
  font-size:.66rem; letter-spacing:.11em; text-transform:uppercase; color:var(--ink3)}
/* EMPTY IS A PROMPT AND NOT A BLANK, once, before anything has been hovered. */
.hoverbar.idle .hbtitle{font-family:var(--meta); font-weight:600; font-size:.66rem;
  line-height:1.2; letter-spacing:.11em; text-transform:uppercase; color:var(--ink3)}

/* TILES: THE SAME WALL WITH THE WORDS AND THE GAPS TAKEN OUT. It is one
   surface of moving-picture stills, which is the thing the grid cannot be
   because a grid is a list of films and this is a wall of them. Denser, too:
   nothing under a tile means a tile can be smaller and still be read. */
.wall.tiles{gap:0; grid-template-columns:repeat(auto-fill,minmax(11rem,1fr))}
@media (max-width:40rem){
  .wall.tiles{gap:0; grid-template-columns:repeat(auto-fill,minmax(7.5rem,1fr))} }
.wall.tiles li.vid{contain-intrinsic-size:auto 7rem}
.wall.tiles .vtitle, .wall.tiles .vmeta, .wall.tiles .vwho{display:none}
/* NO BORDER, BECAUSE A BORDER BETWEEN TWO TOUCHING STILLS IS A TWO-PIXEL SEAM.
   The stills sit directly against each other and the ground shows through
   nothing. */
.wall.tiles .vshot{border:0}
/* AND THE PLAY CONTROL IS NOT DRAWN AT REST. Nine hundred play buttons on one
   screen is a pattern rather than an affordance; one, under the pointer, is
   the affordance. */
.wall.tiles .vplay{opacity:0; transition:opacity .12s ease, background .12s ease, transform .12s ease}
.wall.tiles li.vid a:hover .vplay, .wall.tiles li.vid a:focus-visible .vplay{opacity:1}
@media (prefers-reduced-motion:reduce){ .wall.tiles .vplay{transition:none} }
/* THE HOVER OUTLINE CAME OFF THE TILES, 17 September 2026, with the cover that
   replaced it. It was there because with no gaps and no borders there was
   nothing to say which tile was live; darkening the other eight hundred says
   it far louder, and a gold rule around one frame on top of that is two
   answers to a question that was asked once.
   THE SCALE IS NOT SUPPRESSED HERE ANY MORE EITHER. The note that took it off
   said a growing picture pushes its touching neighbours, and that was simply
   wrong: .vshot carries overflow:hidden, so the image grows inside a box whose
   size never changes and nothing outside it moves. Checked rather than
   reasoned about the second time.
   FOCUS KEEPS ITS RING, because a keyboard cannot see a brightness difference
   it did not cause by moving a pointer. */
.wall.tiles li.vid a:focus-visible .vshot{outline:2px solid var(--accent); outline-offset:-2px}
.wall.tiles .vplate{border-left-width:2px}

/* THE CARD IS DRAWN OR IT IS SKIPPED, and the browser decides which.
   content-visibility lets it skip layout and paint for anything off screen,
   and contain-intrinsic-size tells it how much room to leave so the scrollbar
   does not jump while it does. This is what makes a wall of twelve thousand
   scroll like a wall of sixty. */
li.vid{margin:0; position:relative;
  content-visibility:auto; contain-intrinsic-size:auto 15rem}
li.vid a{display:block; text-decoration:none; color:var(--ink); cursor:pointer}
.vshot{position:relative; display:block; aspect-ratio:16/9; overflow:hidden;
  background:var(--sunk); border:1px solid var(--rule)}
/* THE PICTURE MOVES AND NOTHING ELSE ON THE CARD DOES. The scale is clipped by
   the shot's own overflow, so a still that grows never touches the one beside
   it even with no gap between them, and the slow ease-out is America,
   America's: a picture that snaps reads as a rollover and one that drifts
   reads as a thing coming forward. */
.vshot img{width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .5s cubic-bezier(.2,.6,.2,1), filter .3s ease}
@media (prefers-reduced-motion:reduce){ .vshot img{transition:none} }
li.vid a:hover .vshot img,
li.vid a:focus-visible .vshot img{transform:scale(1.045)}
li.vid a:hover .vshot{border-color:var(--accent-line)}

/* AND THE REST OF THE WALL GOES UNDER A COVER. Pointing at one still darkens
   every other still on the page rather than only lifting the one under the
   pointer. On a wall of nine hundred frames, one frame coming up is a small
   signal in a large field; taking the field away is a large one, and it is the
   difference between a grid that responds and a grid that answers.
   IT IS A FILTER AND NOT A BOX ON TOP. No overlay element, nothing that can
   outlive the state that drew it, and the picture itself doing the work. A
   rule that takes something to nought and relies on a second rule to bring it
   back is one edit away from hiding content for good; a brightness filter
   cannot hide anything.
   ONE SELECTOR HOLDS BOTH HANDS. :has asks whether any still on this wall is
   under the pointer or under the keyboard, and :not excuses the two that could
   be: with a pointer on one frame and focus on another, both stay lit and
   everything else goes dark, which is the only reading of that state that is
   not a wall with nothing lit on it.
   IT ASKS FOR A POINTER FIRST. Touch reports :hover and keeps reporting it
   after the finger has gone, which on this rule is a wall that stays dark
   until the next tap somewhere else. hover:hover is the one question that
   separates a device that can point from one that cannot. */
@media (hover:hover){
  .wall:has(li.vid a:is(:hover,:focus-visible))
    li.vid a:not(:hover):not(:focus-visible) .vshot img{filter:brightness(.7)} }

.vplay{position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  display:flex; align-items:center; justify-content:center;
  width:3.2rem; height:3.2rem; border-radius:50%;
  background:rgba(0,0,0,.62); color:#fff;
  border:1px solid rgba(255,255,255,.5); backdrop-filter:blur(2px);
  transition:background .12s ease, transform .12s ease}
@media (prefers-reduced-motion:reduce){ .vplay{transition:none} }
li.vid a:hover .vplay{background:var(--accent); color:var(--sunk);
  border-color:var(--accent); transform:translate(-50%,-50%) scale(1.07)}
li.vid a:focus-visible .vplay{background:var(--accent); color:var(--sunk)}
@media (max-width:40rem){ .vplay{width:2.4rem; height:2.4rem} }

/* A FILM WITH NO TRAILER KEEPS ITS PLACE AND SAYS WHY. It is not an error and
   it is not hidden: the sweep found the film and found no trailer, and a wall
   that quietly dropped those would be claiming a completeness it does not
   have. The plate carries the studio, which is the one fact the picture would
   have carried. */
.vplate{display:flex; align-items:flex-end; padding:.7rem;
  border-left:3px solid var(--accent-line)}
.vplate span{font-family:var(--meta); font-weight:600; font-size:.6rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink3)}
li.vid.noplay a{cursor:default}
li.vid.noplay .vplay{display:none}

.vtitle{display:block; margin-top:.5rem; font-weight:600; font-size:.88rem;
  line-height:1.32; color:var(--ink)}
li.vid a:hover .vtitle{color:var(--accent)}
.vmeta{display:block; margin-top:.22rem; font-family:var(--meta); font-weight:600;
  font-size:.66rem; letter-spacing:.04em; text-transform:uppercase; color:var(--ink3)}
.vwho{display:block; margin-top:.1rem; font-size:.74rem; color:var(--ink2)}
@media (max-width:40rem){
  .vtitle{font-size:.8rem} .vmeta{font-size:.58rem} .vwho{font-size:.68rem} }

/* NOTHING MATCHED, AND THE PAGE SAYS SO RATHER THAN GOING BLANK. */
.nothing{margin:4rem auto; max-width:34rem; padding:0 1.4rem; text-align:center; color:var(--ink2)}
.nothing h2{font-family:var(--display); font-weight:600; font-size:1.4rem;
  color:var(--title-ink); margin:0 0 .5rem}
.nothing button{margin-top:1rem; font-family:var(--meta); font-weight:600;
  font-size:.7rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--ink); background:var(--ctl); border:1px solid var(--ctl-line);
  border-radius:2px; padding:.5rem .9rem; cursor:pointer}
.nothing button:hover{background:var(--ctl-hover); border-color:var(--ctl-hover-line)}

/* THE SENTINEL. An empty element at the foot of the wall that the script
   watches; when it comes into view the next two hundred cards are appended.
   It carries height so it cannot be missed by an observer that fires on an
   element of zero size. */
.more{height:1px; margin:2rem 0 0}
.loading, .more{padding:0 1.4rem}
.loading{margin:1.4rem 0 0; text-align:center; font-family:var(--meta);
  font-size:.66rem; letter-spacing:.14em; text-transform:uppercase; color:var(--ink3)}

/* THE PLAYER OPENS OVER THE PAGE AND TAKES THE FILM'S OWN SHAPE. The iframe
   is created on open and destroyed on close, which is both how the sound
   stops and how YouTube's player, which is about a megabyte, is never loaded
   by a reader who did not press anything. */
dialog.player{padding:0; border:0; background:none; max-width:min(96vw,74rem);
  width:100%; color:var(--ink); overflow:visible}
/* THE ARROWS NEED ROOM BESIDE THE FILM, and the film is already capped at
   74rem, so the dialog is narrowed rather than the arrows moved inward. */
@media (min-width:66rem){ dialog.player{max-width:min(86vw,68rem)} }
dialog.player::backdrop{background:rgba(0,0,0,.84)}
.pbox{position:relative; aspect-ratio:16/9; background:#000;
  border:1px solid var(--rule)}
.pbox iframe{position:absolute; inset:0; width:100%; height:100%; border:0}
/* A FILM WITH NO TRAILER CAN STILL BE ARROWED THROUGH. The wall holds back
   films that cannot play, so this is only reached when a key dies between one
   sweep and the next, but the arrows must not open an empty black box when it
   happens. */
.pnone{position:absolute; inset:0; display:flex; align-items:center;
  justify-content:center; font-family:var(--meta); font-size:.7rem;
  font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--ink3)}
.pcap{display:flex; align-items:baseline; gap:.8rem; flex-wrap:wrap;
  padding:.7rem .2rem 0}
.pcap h2{margin:0; font-family:var(--display); font-weight:600; font-size:1.1rem;
  color:var(--title-ink)}
.pcap p{margin:0; font-family:var(--meta); font-size:.68rem; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase; color:var(--ink3)}
@media (max-width:66rem){
  .pstep{position:static; width:auto; height:2.6rem; flex:1 1 0; border-radius:2px;
    background:var(--ctl)}
  dialog.player{display:flex; flex-wrap:wrap; gap:.6rem}
  .pbox{flex:1 0 100%; order:1}
  .pcap{flex:1 0 100%; order:2}
  .pwhere{flex:1 0 100%; order:3; margin-top:.2rem}
  .pprev{order:4} .pnext{order:5}
  .pclose{top:-2.3rem}
}
/* THE ARROWS SIT OUTSIDE THE PICTURE AND NOT ON IT. On it they would cover
   the film and fight YouTube's own controls, which live along the bottom edge
   and in the middle. Beside it they are always in the same place and never
   over anything. On a narrow screen there is no room beside, so they come down
   under the caption and become two big targets a thumb can hit. */
.pstep{position:absolute; top:calc(50% - 1.6rem); z-index:2;
  display:flex; align-items:center; justify-content:center;
  width:3.2rem; height:3.2rem; padding:0; border-radius:50%;
  background:rgba(0,0,0,.5); color:var(--ink);
  border:1px solid var(--ctl-line); cursor:pointer;
  transition:background .12s ease, color .12s ease, border-color .12s ease}
.pprev{left:-4.2rem}
.pnext{right:-4.2rem}
.pstep:hover{background:var(--ctl-on); color:var(--accent); border-color:var(--accent)}
.pstep:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
/* AN END IS SHOWN AND NOT HIDDEN. A control that disappears at the last film
   moves the other one, and a reader who was pressing in one place is suddenly
   pressing in another. */
.pstep[disabled]{opacity:.25; cursor:default; background:none}
.pstep[disabled]:hover{background:none; color:var(--ink); border-color:var(--ctl-line)}
@media (prefers-reduced-motion:reduce){ .pstep{transition:none} }

/* WHERE YOU ARE IN THE SET YOU FILTERED, which is the one thing arrows cannot
   say by themselves: eleven of ninety-four tells a reader both that there is
   more and how much. */
.pwhere{margin:.5rem .2rem 0; font-family:var(--meta); font-weight:600;
  font-size:.62rem; letter-spacing:.14em; text-transform:uppercase; color:var(--ink3)}

.pclose{position:absolute; top:-2.5rem; right:0; background:var(--ctl);
  color:var(--ctl-ink); border:1px solid var(--ctl-line); border-radius:2px;
  font-family:var(--meta); font-weight:600; font-size:.66rem; letter-spacing:.13em;
  text-transform:uppercase; padding:.35rem .7rem; cursor:pointer}
.pclose:hover{background:var(--ctl-hover); color:var(--ctl-hover-ink);
  border-color:var(--ctl-hover-line)}

/* THE FOOT, AND IT IS ONE LINE. There are no other pages to link to. */
footer.foot{margin-top:2rem; border-top:1px solid var(--rule);
  background:linear-gradient(var(--stripe), var(--footer-glow))}
.footin{display:flex; flex-wrap:wrap; gap:.4rem 1.6rem; align-items:baseline;
  padding:1.5rem 0 1.8rem}
.footin p{margin:0; font-family:var(--meta); font-size:.64rem; font-weight:600;
  letter-spacing:.1em; text-transform:uppercase; color:var(--ink3)}
.footin a{color:var(--ink2); text-decoration:none; border-bottom:1px solid var(--rule)}
.footin a:hover{color:var(--accent); border-bottom-color:var(--accent)}
.footin .seedline{color:var(--accent)}
