/* Chroma Noir — the reels wall
   ---------------------------------------------------------------------------
   The third wall. Films are 16:9 posters, photographs are a contact sheet,
   reels are 9:16 — and the ratio is the only thing that genuinely differs.
   Everything else is deliberately the films wall's vocabulary, down to the
   class names, so the two stylesheets can be read side by side: .tile__a,
   .tile__still, .tile__img, .tile__edge, .tile__wait, .tile__dark, .tile__t,
   .tile__m, .tile__no, .len, .gate, .lede, .none, .cbtn, .sr.

   THREE THINGS THIS FILE DOES THAT films.css DOES NOT:

     1. THE TRACK SIZE IS A FACT ABOUT THE LIBRARY. .wall--1 … .wall--4 give
        a 280px track and exactly as many columns as there are reels; five or
        more fall back to auto-fill at 168px. Three tiles sitting in the first
        three of eight phantom auto-fill tracks reads as a bug, and with four
        reels on the wall it would be the first thing anybody saw.

     2. THREE ACROSS ON A PHONE, not two. A 9:16 object two across a 390px
        phone is 306px tall, and a wall of those is a list.

     3. THE VIEWER IS TWO COLUMNS WHEREVER THERE IS ROOM, phone-landscape
        included. A vertical object leaves the band free, so the chrome goes
        beside the picture rather than over it.

   NO NEW GOLD. The tile keeps the films wall's gold hairline sweep — that is
   the tile vocabulary and not a new mark — and the focus rings stay gold
   because they are the house's and the television has nothing else. The
   viewer chrome, the share sheet and the follow row get none at all, and a
   copy confirmation is --ink.

   CHROME 79 (the wall TV, 1920x1070) IS THE FLOOR. No `inset` shorthand, no
   flex `gap` (grid gap is Chrome 66 and is fine), no :has(), no nesting, no
   dvh, every svh preceded by a plain fallback, no bare aspect-ratio, and
   :focus-visible NEVER in a selector list with a rule the television needs —
   a list is dropped whole when one selector in it cannot be parsed, so every
   focus rule is its own block with an .is-on or :focus twin beside it.
*/

:root{
  --ink:#f4f3f1; --dim:#9a9894; --faint:#6a6764; --gold:#c9a14a;
  /* NEW, AND MEASURED. --faint is 3,75:1 on black and fails AA for body text.
     The lede and the empty state keep it to match the other two walls, which
     is a knowing, pre-existing failure of the house. Copy whose whole job is
     to be read — the honest sentence in the share sheet, the admin notice
     under the follow row — takes this instead: #7e7b77 is 4,99:1. */
  --faint2:#7e7b77;
  --rule:rgba(244,243,241,.14);
  --rule2:rgba(244,243,241,.34);
  --sans:'Inter Tight',-apple-system,'Segoe UI',sans-serif;
  --serif:'Fraunces',Georgia,serif;
  --pad:clamp(16px,4vw,56px);
  --wide:1760px;
  --ease:cubic-bezier(.22,.61,.36,1);
  --s1:4px; --s2:8px; --s3:12px; --s4:16px;
  --s5:24px; --s6:32px; --s7:48px; --s8:64px;
  color-scheme:dark;
}
*{box-sizing:border-box}
body{margin:0;background:#000;color:var(--ink);font-family:var(--sans);
     font-synthesis:none;-webkit-font-smoothing:antialiased}
[hidden]{display:none !important}

/* ---- the ground ----------------------------------------------------------- */
.scrim--flat{position:fixed;top:0;right:0;bottom:0;left:0;z-index:0;pointer-events:none;
  background:linear-gradient(rgba(244,243,241,.035) 0%,rgba(0,0,0,0) 38%)}

/* THE SAFE AREA, written as a pair every time: a plain value on the line
   before and the env() version after it. env() is Chrome 69 for this spelling
   and the television is 79, where an unsupported env() drops the WHOLE
   declaration — and a dropped padding is a layout touching the frame. */
.page{position:relative;z-index:2;max-width:var(--wide);margin:0 auto;
      padding:0 var(--pad) clamp(44px,9vh,96px);
      padding-left:calc(var(--pad) + env(safe-area-inset-left));
      padding-right:calc(var(--pad) + env(safe-area-inset-right));
      padding-bottom:calc(clamp(44px,9vh,96px) + env(safe-area-inset-bottom))}

/* ---- chrome ---------------------------------------------------------------
   Margins on the children rather than flex gap, which is Chrome 84 and
   silently zero on the television. */
.bar{display:flex;flex-wrap:wrap;align-items:center;padding:17px 0;
     padding-top:calc(17px + env(safe-area-inset-top))}
.bar > *{margin:5px 0}
.bar > * + *{margin-left:18px}
.link{display:inline-flex;align-items:center;border:0;padding:0;background:none;
      font:inherit;font-size:14px;font-weight:500;color:var(--dim);text-decoration:none;
      cursor:pointer;transition:color .25s}
.link > span{margin-right:10px;transition:margin-right .25s}
.link:hover{color:var(--ink)}
.link:hover > span{margin-right:15px}
.link:focus-visible{outline:2px solid var(--gold);outline-offset:4px}
.bar__gap{flex:1 1 auto}

.lede{margin:0 0 clamp(14px,2.4vh,30px);font-family:var(--serif);font-style:italic;
      font-weight:300;font-size:clamp(15px,1.6vw,19px);color:var(--faint);
      min-height:1.3em}
.note{margin:0 0 18px;font-size:13px;line-height:1.6;color:var(--gold)}
.none{margin:22px 0 0;font-family:var(--serif);font-style:italic;font-weight:300;
      font-size:clamp(16px,1.8vw,20px);color:var(--faint)}

/* ---- the wall --------------------------------------------------------------
   FIVE OR MORE REELS: auto-fill at a 168px track. min(168px,100%) rather than
   a bare 168px — auto-fill cannot make a track narrower than its minimum, so
   on a window under about 200px the grid would be wider than the page and the
   whole document would scroll sideways. */
.wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(168px,100%),1fr));
  gap:clamp(20px,2.6vw,34px) clamp(14px,1.8vw,24px)}

/* FOUR OR FEWER: a bigger tile and EXACTLY as many columns as there are reels.
   auto-fill at 280px would still lay eight tracks across a 1760px measure and
   park three tiles in the first three of them, which reads as a grid that has
   lost something rather than as a wall with three reels on it.

   minmax(0,280px) and not a bare 280px: the tracks may shrink below their
   ideal on a narrow window, which is what stops four columns overflowing a
   700px one. justify-content:start keeps them at the gutter instead of
   stretching one reel across the whole page. */
.wall--1{grid-template-columns:minmax(0,280px);justify-content:start}
.wall--2{grid-template-columns:repeat(2,minmax(0,280px));justify-content:start}
.wall--3{grid-template-columns:repeat(3,minmax(0,280px));justify-content:start}
.wall--4{grid-template-columns:repeat(4,minmax(0,280px));justify-content:start}

/* THREE ACROSS ON A PHONE, and the same reasoning one step further: a wall of
   one or two reels at a third of a 390px screen is three small stamps with a
   third of the row empty, so the count still decides. Explicit columns rather
   than a lower minmax, because deterministic beats whatever the tracks happen
   to add up to. */
@media (max-width:520px){
  .wall{grid-template-columns:repeat(3,minmax(0,1fr))}
  .wall--1{grid-template-columns:minmax(0,1fr)}
  .wall--2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .wall--3{grid-template-columns:repeat(3,minmax(0,1fr))}
  .wall--4{grid-template-columns:repeat(3,minmax(0,1fr))}
}

.tile__a{display:block;width:100%;text-align:left;text-decoration:none;color:inherit}

/* .is-on IS NOT DECORATION, it is the television's focus ring. :focus-visible
   does not exist before Chrome 86 and the wall TV runs Chrome 79, where a
   selector containing it is thrown away whole — so a remote would walk an
   unmarked grid with nothing at all to say where it was. The class is set by
   the page in markOn(), and every rule below that answers focus answers it
   too.

   THE RING NEEDS A COMPANION OVER A PICTURE. Gold is 8,72:1 on black, but
   these rings sit over a FRAME, and gold on a blown-out one can fall under
   3:1. The dark halo costs nothing on black and saves the ring on white.
   Two rules, never one list. */
.tile__a:focus-visible{outline:2px solid var(--gold);outline-offset:3px;
  box-shadow:0 0 0 4px rgba(0,0,0,.65)}
.tile__a.is-on{outline:2px solid var(--gold);outline-offset:3px;
  box-shadow:0 0 0 4px rgba(0,0,0,.65)}

/* THE RATIO IS A PADDING BOX FIRST. aspect-ratio arrived in Chrome 88 and the
   wall TV is Chrome 79, where the box would have no height at all and the
   whole grid would collapse into a column of captions. 177.78% is 16/9 the
   other way up. @supports hands the modern property to browsers that have it. */
.tile__still{display:block;position:relative;overflow:hidden;
  border:1px solid var(--rule);border-radius:2px;background:#050505;
  transition:border-color .3s}
.tile__still::before{content:"";display:block;padding-top:177.78%}
@supports (aspect-ratio:9/16){
  .tile__still{aspect-ratio:9/16}
  .tile__still::before{display:none}
}
.tile__a:hover .tile__still{border-color:var(--rule2)}

/* Longhand rather than `inset`, for the same Chrome 79 reason. */
.tile__img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;
  object-fit:cover;display:block;
  filter:grayscale(1) contrast(1.06) brightness(.78);
  transition:filter .45s ease,transform .45s var(--ease);transform:scale(1.005)}
/* EVERY PAYOFF RULE IS WRITTEN TWICE, and it is not duplication for its own
   sake: a selector LIST is dropped whole when one selector in it cannot be
   parsed, so putting .is-on in the same list as the fallback it is meant to BE
   takes the fallback down with the thing it was covering for. */
.tile__a:hover .tile__img,.tile__a:focus-visible .tile__img{
  filter:grayscale(0) contrast(1) brightness(1);transform:scale(1.03)}
.tile__a.is-on .tile__img{
  filter:grayscale(0) contrast(1) brightness(1);transform:scale(1.03)}

/* The preview, over the still inside the same box. It fades in only once it is
   genuinely playing, so a slow connection shows the frame rather than black. */
.tile__vid{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;
  object-fit:cover;display:block;opacity:0;transition:opacity .45s ease}
.tile__vid.on{opacity:1}

/* THE ONE GOLD MARK ON A TILE, and it is the films wall's, unchanged.
   z-index because the preview is APPENDED AFTER these two, and among
   positioned siblings with no z-index the last one in the markup wins. */
.tile__edge{position:absolute;left:0;right:0;bottom:0;height:1px;z-index:2;
  background:var(--gold);
  transform:scaleX(0);transform-origin:left;transition:transform .5s var(--ease)}
.tile__a:hover .tile__edge,.tile__a:focus-visible .tile__edge{transform:scaleX(1)}
.tile__a.is-on .tile__edge{transform:scaleX(1)}

/* Fills while a preview loads, so resting on a tile says something is
   happening rather than nothing for half a second. Under the gold edge,
   deliberately: one is progress, the other is the answer. */
.tile__wait{position:absolute;left:0;bottom:0;height:1px;width:0;z-index:2;
  background:rgba(244,243,241,.5);transition:width .45s linear}
.tile__a.loading .tile__wait{width:100%}

/* A TILE WITH NO PICTURE. There is one honest reason for one here — the reel
   has no poster on file — and it says so rather than showing a broken image.
   MARGIN, NOT GAP: flex gap is Chrome 84 and silently zero on the television. */
.tile__dark{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;
  flex-direction:column;align-items:center;justify-content:center;
  background:#070707}
.tile__dark > * + *{margin-top:9px}
/* text-indent cancels the trailing letter-space: tracking adds a gap AFTER the
   last character as well as between them, so a centred word sits half a
   letter-space to the left of where it looks like it should. */
.tile__none{font-size:9.5px;font-weight:500;letter-spacing:.22em;text-indent:.22em;
  text-transform:uppercase;color:var(--dim)}

.tile__t{display:block;font-family:var(--serif);font-weight:300;font-size:16.5px;
  line-height:1.18;letter-spacing:-.01em;color:var(--dim);margin-top:11px;
  overflow-wrap:break-word;transition:color .3s}
.tile__a:hover .tile__t,.tile__a:focus-visible .tile__t{color:var(--ink)}
.tile__a.is-on .tile__t{color:var(--ink)}
/* AT THREE ACROSS ON A PHONE the measure is about 108px at 390. It has to sit
   AFTER the rule above: a media query adds no specificity, so the same
   selector later in the file wins wherever it is written. */
@media (max-width:520px){
  .tile__t{font-size:14px;line-height:1.22;margin-top:8px}
}
.tile__m{display:flex;align-items:baseline;margin-top:7px}
.tile__m > * + *{margin-left:9px}
.tile__no{font-size:9.5px;letter-spacing:.2em;color:var(--dim);
  font-variant-numeric:tabular-nums;transition:color .35s}
.tile__a:hover .tile__no,.tile__a:focus-visible .tile__no{color:var(--gold)}
.tile__a.is-on .tile__no{color:var(--gold)}
.tile__sp{flex:1 1 auto}
/* --dim at rest rather than --faint: at twelve pixels this is the one label
   somebody may read before pressing anything, and --faint is about 3,7:1 on
   black — a size and a contrast agreeing with each other in the wrong
   direction. */
.len{font-size:12px;color:var(--dim);font-variant-numeric:tabular-nums}

/* ---- the gate -------------------------------------------------------------
   The films wall's line, built from one integer. It does not advertise and it
   does not hide: someone who is meant to know already knows, and everyone else
   reads a sentence and moves on. NO PADLOCK — a padlock says "press me" and
   there is no form behind this one, only a permission on a portal account. */
.gate{margin:clamp(20px,3.5vh,44px) 0 0;padding-top:clamp(14px,2vh,22px);
      border-top:1px solid var(--rule)}
.gate__say{margin:0;font-family:var(--serif);font-style:italic;font-weight:300;
           font-size:clamp(14px,1.4vw,17px);color:var(--faint);
           text-shadow:0 1px 10px rgba(0,0,0,.95)}
.gate__link{color:var(--dim);text-decoration:underline;text-underline-offset:.2em;
            text-decoration-thickness:1px;transition:color .25s}
.gate__link:hover{color:var(--gold)}
.gate__link:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

/* ---- the follow row --------------------------------------------------------
   Absent entirely when the owner has filled in no handle — the same precedent
   as the films page's featured hero, which is not there rather than empty when
   no film is flagged. NO GOLD: these are three links to somewhere else, not
   the page's own emphasis. */
.follow{margin:clamp(20px,3.5vh,44px) 0 0;padding-top:clamp(14px,2vh,22px);
        border-top:1px solid var(--rule)}
.follow__k{margin:0 0 12px;font-size:9.5px;font-weight:500;letter-spacing:.24em;
           text-transform:uppercase;color:var(--dim)}
.follow__row{display:flex;flex-wrap:wrap;align-items:center}
.follow__row > *{margin:4px 0}
.follow__row > * + *{margin-left:10px}
/* The house ghost button: 2px radius, a hairline border, no fill. */
.fbtn{display:inline-flex;align-items:center;border:1px solid var(--rule);
      border-radius:2px;padding:8px 16px;background:none;color:var(--dim);
      font:inherit;font-size:12px;font-weight:500;letter-spacing:.06em;
      text-decoration:none;cursor:pointer;
      transition:color .22s,border-color .22s,background-color .22s}
.fbtn:hover{color:var(--ink);border-color:var(--rule2);background:rgba(244,243,241,.05)}
.fbtn:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* THE ONE LINE ONLY THE ADMIN EVER SEES. --faint2 rather than --faint: it is a
   sentence whose whole job is to be read, by the one person who can act on it. */
.follow__admin{margin:0;font-size:12.5px;line-height:1.6;color:var(--faint2)}
.follow__admin a{color:var(--dim);text-decoration:underline;text-underline-offset:.2em;
                 text-decoration-thickness:1px;transition:color .25s}
.follow__admin a:hover{color:var(--ink)}
.follow__admin a:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

/* ---- the viewer ------------------------------------------------------------
   Longhand offsets, not the `inset` shorthand: that is Chrome 87 and the wall
   TV is Chrome 79, where a fixed element with no offsets at all sits at its
   static position and the player stops being an overlay.

   THE BASE IS THE STACKED LAYOUT — picture at the top, words under it — which
   is what a phone held upright needs and what every narrow window gets. The
   two-column composition is an enhancement added at 860px and, separately, in
   short landscape. Written this way round because the stacked case is the one
   that needs the simpler box: the film is capped in vh/svh, which are real
   lengths and need no containing block to resolve against. */
.reel{position:fixed;top:0;right:0;bottom:0;left:0;z-index:60;
      display:grid;grid-template-rows:auto auto;grid-template-columns:minmax(0,1fr);
      align-content:start;row-gap:clamp(10px,1.8vh,24px);
      overflow-y:auto;
      background:rgba(0,0,0,.94);
      padding:clamp(16px,3.2vh,44px) clamp(14px,3vw,40px);
      /* position:fixed over the whole viewport is exactly where the insets
         bite. Plain value first, env() after — see .page. */
      padding:calc(clamp(16px,3.2vh,44px) + env(safe-area-inset-top))
              calc(clamp(14px,3vw,40px) + env(safe-area-inset-right))
              calc(clamp(16px,3.2vh,44px) + env(safe-area-inset-bottom))
              calc(clamp(14px,3vw,40px) + env(safe-area-inset-left))}
@supports ((-webkit-backdrop-filter:blur(18px)) or (backdrop-filter:blur(18px))){
  .reel{-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}
}

.reel__stage{position:relative;min-width:0}
/* THE PLAIN vh FIRST. Without it a browser with no svh drops the whole
   declaration and the reel gets no ceiling at all — a 9:16 object with no
   ceiling is taller than the window by construction. */
.reel__stage video{display:block;margin:0 auto;width:auto;height:auto;
  max-width:100%;max-height:62vh;max-height:62svh;background:#000;
  border-radius:2px}

.reel__chrome{display:flex;flex-direction:column;min-width:0;min-height:0}
.reel__chrome > * + *{margin-top:var(--s4)}
.reel__id{display:flex;flex-wrap:wrap;align-items:baseline;min-width:0}
.reel__id > *{margin:4px 0}
.reel__id > * + *{margin-left:18px}
/* --dim, not --faint: these are 11px and 12px, and --faint is 3,74:1 on black. */
.reel__no{font-size:11px;letter-spacing:.2em;color:var(--dim);
          font-variant-numeric:tabular-nums}
.reel__t{font-family:var(--serif);font-weight:300;font-size:clamp(19px,2.3vw,28px);
         letter-spacing:-.01em;color:var(--ink);min-width:0;overflow-wrap:break-word}
.reel__len{font-size:12px;color:var(--dim);font-variant-numeric:tabular-nums}
.reel__desc{margin:0;max-width:52ch;font-size:13px;line-height:1.6;color:var(--dim)}
.reel__acts{display:flex;flex-wrap:wrap;align-items:center}
.reel__acts > *{margin:4px 0}
.reel__acts > * + *{margin-left:6px}

/* NO GOLD IN THE VIEWER CHROME. The films player's .cbtn goes gold on hover;
   here the same box answers in --ink against a brighter hairline, because the
   gold on this page is spent on the tile's sweep and on the focus ring. The
   FOCUS ring stays gold: it is the house's, and the television has nothing
   else to show where it is. */
.cbtn{border:1px solid var(--rule);border-radius:999px;background:none;color:var(--dim);
      font:inherit;font-size:12px;font-weight:500;padding:7px 15px;cursor:pointer;
      transition:color .2s,border-color .2s,background-color .2s}
.cbtn:hover:not(:disabled){color:var(--ink);border-color:var(--rule2)}
.cbtn:disabled{opacity:.3;cursor:default}
.cbtn[aria-expanded="true"]{color:var(--ink);border-color:var(--rule2);
  background:rgba(244,243,241,.06)}
.cbtn:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

/* ---- how the wall is ordered ------------------------------------------------
   THE FILMS WALL'S OWN CONTROL, copied rather than shared: these are two
   hand-written pages with no build step and no stylesheet between them, so the
   choice was a copy or a third file. Copied, and named the same, so the two
   walls stay recognisably one house — if one of them changes, change both.

   MARGIN, NOT GAP. Flex gap is Chrome 84 and the wall television is 79, where
   the row would close up into one unreadable string of words. */
.sortrow{margin:0 0 clamp(14px,2.2vh,26px)}
.sortbox{display:inline-flex;flex-wrap:wrap;align-items:baseline}
/* The vertical margin is for the wrapped case on a narrow phone, where two
   rows of buttons would otherwise touch. */
.sortbox > *{margin:3px 0}
.sortbox > * + *{margin-left:9px}
.rail__k{font-size:10.5px;font-weight:500;letter-spacing:.11em;
  text-transform:uppercase;color:var(--faint2)}
.tbtn{border:0;padding:0;background:none;font:inherit;cursor:pointer;
  font-size:10.5px;font-weight:500;letter-spacing:.11em;text-transform:uppercase;
  color:var(--dim);transition:color .22s;white-space:nowrap}
.tbtn:hover{color:var(--ink)}
.tbtn[aria-pressed="true"]{color:var(--ink)}
/* Two rules, never one list — the reason given over .tile__a:focus-visible. */
.tbtn:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.tsep{color:var(--rule2);font-size:11px}

/* A BIGGER TARGET, NOT A BIGGER BUTTON, and the type floor that goes with it.
   Both are the films wall's, to the pixel: 34px visual plus 5px top and bottom
   is 44px of target with no pixel of the design moved, and the row's own
   separation widens first so two neighbouring extenders cannot overlap. */
@media (pointer: coarse){
  .sortbox > * + *{margin-left:14px}
  .tbtn{position:relative;min-height:34px;font-size:11px}
  .tbtn::after{content:"";position:absolute;top:-5px;right:0;bottom:-5px;left:0}
  .rail__k{font-size:10px}
}

/* ---- the admin's two -------------------------------------------------------
   .cbtn is written for a <button>; an <a> wearing it needs the three things a
   button gets for free. Written as its own rule rather than folded into .cbtn,
   so nothing changes for the four buttons that were already there. */
a.cbtn{display:inline-block;text-decoration:none;line-height:normal}
a.cbtn:hover{color:var(--ink);border-color:var(--rule2)}

/* DELETE LOOKS LIKE THE OTHERS UNTIL IT IS ARMED. Nothing on this page shouts,
   and at rest this is one more quiet pill; it is the SECOND press that has to
   look unlike the first, so the colour arrives with the armed state and leaves
   with it six seconds later. The only red on the subdomain, and it is on
   screen for six seconds at a time.

   Two rules rather than one list, to match the rest of this file. */
.cbtn--del.armed{color:#e8a49a;border-color:#8c4034;background:rgba(140,64,52,.22)}
.cbtn--del.armed:hover:not(:disabled){color:#f6d7d1;border-color:#b05545}

/* ---- the share sheet -------------------------------------------------------
   A SHEET, NOT THREE LOGO BUTTONS. Two of the three platforms anybody would
   expect to see here cannot be shared to from a web page at all, so the row
   holds only what works and the sentence underneath names the two that do not
   and says what to do instead. See the comment in index.html. */
.shr{border:1px solid var(--rule);border-radius:2px;padding:14px 16px 15px;
     background:rgba(244,243,241,.03)}
.shr__k{margin:0 0 12px;font-size:9.5px;font-weight:500;letter-spacing:.24em;
        text-transform:uppercase;color:var(--dim)}
.shr__row{display:flex;flex-wrap:wrap;align-items:center}
.shr__row > *{margin:4px 0}
.shr__row > * + *{margin-left:8px}
.shr__b{display:inline-flex;align-items:center;border:1px solid var(--rule);
        border-radius:2px;padding:8px 14px;background:none;color:var(--dim);
        font:inherit;font-size:12px;font-weight:500;letter-spacing:.04em;
        text-decoration:none;cursor:pointer;
        transition:color .22s,border-color .22s,background-color .22s}
.shr__b:hover:not(:disabled){color:var(--ink);border-color:var(--rule2);
        background:rgba(244,243,241,.05)}
.shr__b:disabled{opacity:.45;cursor:default}
.shr__b:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* THE HONEST SENTENCE, and it is always visible rather than tucked behind a
   question mark: it is the reason two buttons somebody is looking for are not
   here, and a reason nobody reads is not a reason. --faint2, because this is
   copy whose whole job is to be read.

   .shr__why is the same type for the occasional third case — why Facebook is
   not drawn for this caller — and it sits between the row and the standing
   sentence rather than inside the row, so it is never a flex item whose
   position depends on how wide the column happens to be. */
.shr__say,.shr__why{margin:12px 0 0;max-width:46ch;font-size:12.5px;
          line-height:1.6;color:var(--faint2)}
/* "Link copied." and nothing more decorative than that. --ink rather than
   gold: a confirmation is not an accent. */
.shr__out{margin:10px 0 0;min-height:1.3em;font-size:12.5px;line-height:1.5;
          color:var(--ink)}

.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---- the device classes -----------------------------------------------------
   One layout, bent where a device actually differs. Nothing below is keyed to
   a device NAME: the questions are can the pointer hover, is the screen narrow,
   how short is it, and is the type being read from across a room. A breakpoint
   cannot be a custom property — a media-query condition will not take one and
   there is no preprocessor — so the register is listed here instead:

     (max-width:520px)                                phone: wall 3-up, phone
                                                      type scale
     (min-width:860px)                                the viewer splits into
                                                      two columns
     (max-height:560px) and (orientation:landscape)   a phone held sideways and
                                                      any short window: the
                                                      viewer splits there too
     (min-width:1900px)                               --wide:2040px
     (pointer:coarse)                                 targets, hover undo,
                                                      type floor
     (hover:none)                                     the press payoff
     (prefers-reduced-motion:reduce)                  motion off
     .is-tv                                           from the UA. SIZE ONLY.
   -------------------------------------------------------------------------- */

/* ---- a touch screen ------------------------------------------------------ */
@media (pointer:coarse){
  /* 32px high is a mouse target. A finger needs 44, which is the figure both
     Apple and Google publish. */
  .cbtn{padding:12px 18px;font-size:13px;min-height:44px}
  .shr__b,.fbtn{padding:12px 16px;font-size:13px;min-height:44px}
  /* HOVER STYLING STICKS AFTER A TAP on a touch screen, leaving a tile looking
     chosen long after the finger has gone — which on a wall reads as "this one
     is playing". Focus is set by a key or by the page and never by a finger, so
     the focus half of each pair survives untouched. */
  .tile__a:hover .tile__img{filter:grayscale(1) contrast(1.06) brightness(.78);
    transform:scale(1.005)}
  .tile__a:hover .tile__edge{transform:scaleX(0)}
  .tile__a:hover .tile__no{color:var(--dim)}
  .tile__a:hover .tile__t{color:var(--dim)}
  /* A TYPE FLOOR, keyed to coarse rather than to width: the reason is
     sub-pixel rendering plus the finger, and a 390px desktop window needs
     neither. */
  .tile__no{font-size:10px}
  .reel__no{font-size:11px}
  .shr__say,.shr__why,.follow__admin{font-size:13px}
}

/* ---- a finger, where a pointer would have hovered -------------------------
   NOTHING PREVIEWS ON TOUCH, and that is the decision rather than an omission
   — see wantPreview() in reels.js. But a finger got no answer at all until the
   reel opened, so the hover payoff arrives on the press instead: the same two
   gestures, colour returning and the gold hairline drawing, on :active. */
@media (hover:none){
  .tile__a:active .tile__img{
    filter:grayscale(0) contrast(1) brightness(1);transform:scale(1.015);
    transition:filter 160ms var(--ease),transform 160ms var(--ease)}
  .tile__a:active .tile__edge{transform:scaleX(1);transition:transform 180ms var(--ease)}
  .tile__a:active .tile__t{color:var(--ink)}
  /* A long press on a tile offers "Download linked file" / "Save image" on
     both iOS and Android. Friction rather than protection, but it is the one
     place the page invites a gesture and then looks careless. */
  .tile__a,.tile__img{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
}

/* ---- a window with room: the viewer becomes two columns --------------------
   REEL LEFT, CHROME RIGHT. A 9:16 object in a landscape window is limited by
   HEIGHT, so it can never be more than about a third of the width — and the
   black either side of it is the only place on this page where a title and
   four buttons can sit without covering a picture. Grid `gap` is Chrome 66, so
   the television is safe; it is FLEX gap that is Chrome 84. */
@media (min-width:860px){
  .reel{grid-template-rows:minmax(0,1fr);
        grid-template-columns:minmax(0,1fr) minmax(260px,32%);
        column-gap:clamp(20px,2.6vw,44px);row-gap:0;align-content:stretch;
        overflow-y:hidden}
  .reel__stage{grid-column:1;grid-row:1;min-height:0}
  .reel__chrome{grid-column:2;grid-row:1;justify-content:center;overflow-y:auto}
  /* THE REEL IS POSITIONED AGAINST THE STAGE rather than laid out inside it,
     and that is deliberate. Laid out as an ordinary centred item it takes its
     width from the intrinsic size and max-height:100% resolves to nothing at
     all — a percentage needs a containing block with a definite height, and a
     1fr track does not give one. An absolutely positioned box resolves its
     percentages against the containing block's USED size, which is always
     available, so four zero offsets with auto margins centre the reel and,
     whatever its shape, it cannot escape the stage. Longhand, never `inset`. */
  .reel__stage video{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;
    max-width:100%;max-height:100%}
}

/* ---- a phone held sideways, and any short window ---------------------------
   Keyed on HEIGHT, because what is scarce in landscape is the height and
   max-width cannot see it. 560px clears every phone in landscape (iPhone SE
   320 · 15 Pro Max 430 · 16 Pro Max 440 · Pixel 8 Pro 448) and excludes every
   tablet (iPad mini 744 · iPad Pro 11" 834 · iPad Pro 13" 1024).

   A phone in landscape is about 844x390, so (min-width:860px) above does NOT
   match it and the two-column rules have to be written again here. They are
   the same rules with a tighter frame: at 844x390 the reel is 219px wide and
   the chrome gets the ~310px beside it. */
@media (max-height:560px) and (orientation:landscape){
  .reel{grid-template-rows:minmax(0,1fr);
        grid-template-columns:minmax(0,1fr) minmax(200px,44%);
        column-gap:clamp(14px,2.4vw,28px);row-gap:0;align-content:stretch;
        overflow-y:hidden;
        padding:clamp(10px,2.4vh,18px) clamp(12px,2.4vw,24px);
        padding:calc(clamp(10px,2.4vh,18px) + env(safe-area-inset-top))
                calc(clamp(12px,2.4vw,24px) + env(safe-area-inset-right))
                calc(clamp(10px,2.4vh,18px) + env(safe-area-inset-bottom))
                calc(clamp(12px,2.4vw,24px) + env(safe-area-inset-left))}
  .reel__stage{grid-column:1;grid-row:1;min-height:0}
  .reel__chrome{grid-column:2;grid-row:1;justify-content:center;overflow-y:auto}
  .reel__chrome > * + *{margin-top:10px}
  .reel__stage video{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;
    max-width:100%;max-height:100%}
  .reel__t{font-size:19px}
  /* The description is the first thing to go when there is no room for it: the
     title, the controls and the picture are what the window is for. */
  .reel__desc{display:none}
  .shr__say,.shr__why{font-size:11.5px;line-height:1.5}
}

/* 1.760px leaves a third of a 2560px monitor black. Nothing below 1900 moves. */
@media (min-width:1900px){
  :root{--wide:2040px}
}

/* ---- a television -------------------------------------------------------- */
/* Set from the user agent, which is a guess, and therefore used for NOTHING
   BUT SIZE — see IS_TV in reels.js. At three metres, 11px is not small type,
   it is an absence of type. The padding is for overscan: a television may crop
   several per cent of every edge, and anything flush to the frame is simply
   not on the screen. */
.is-tv body{font-size:18px}
.is-tv .page{padding-left:clamp(40px,4vw,72px);padding-right:clamp(40px,4vw,72px);
             padding-bottom:clamp(40px,5vh,64px)}
.is-tv .bar{padding-top:clamp(28px,3.5vh,44px);padding-bottom:clamp(10px,1.5vh,18px)}
.is-tv .link{font-size:20px}
.is-tv .lede{font-size:24px}
.is-tv .none{font-size:22px}
.is-tv .gate__say{font-size:21px}
.is-tv .follow__k{font-size:14px}
.is-tv .fbtn{font-size:17px;padding:10px 22px}
.is-tv .follow__admin{font-size:18px}
/* FEWER, BIGGER TILES, and the count still decides the track. A 9:16 tile at
   260px is 462px tall, which puts two rows on a 1070px screen; at 360px it is
   640px tall, which is right when there are four reels and wrong when there
   are twenty. */
.is-tv .wall{grid-template-columns:repeat(auto-fill,minmax(min(260px,100%),1fr))}
.is-tv .wall--1{grid-template-columns:minmax(0,360px)}
.is-tv .wall--2{grid-template-columns:repeat(2,minmax(0,360px))}
.is-tv .wall--3{grid-template-columns:repeat(3,minmax(0,360px))}
.is-tv .wall--4{grid-template-columns:repeat(4,minmax(0,360px))}
.is-tv .tile__t{font-size:26px;margin-top:14px}
.is-tv .tile__no{font-size:15px}
.is-tv .tile__none{font-size:15px}
.is-tv .len{font-size:17px}
.is-tv .reel__no{font-size:16px}
.is-tv .reel__len{font-size:17px}
.is-tv .reel__desc{font-size:19px;max-width:none}
.is-tv .cbtn{font-size:17px;padding:10px 22px}
.is-tv .shr__k{font-size:14px}
.is-tv .shr__b{font-size:17px;padding:10px 20px}
.is-tv .shr__say,.is-tv .shr__why{font-size:17px;max-width:none}
.is-tv .shr__out{font-size:17px}
/* A remote has no pointer: the focus ring is the only thing telling anyone
   where they are, so it is drawn to be seen from the sofa. */
.is-tv .tile__a:focus-visible,.is-tv .cbtn:focus-visible,.is-tv .link:focus-visible,
.is-tv .shr__b:focus-visible,.is-tv .fbtn:focus-visible{
  outline:3px solid var(--gold);outline-offset:5px}
/* THE ONE THAT ACTUALLY FIRES ON THE TELEVISION, whose browser predates
   :focus-visible. Each in a rule of its OWN, because a selector list is
   dropped whole when one selector in it cannot be parsed — which is exactly
   how the rule above is invisible to Chrome 79. Plain :focus, scoped to .is-tv
   so that no other screen gains a ring after a mouse click. */
.is-tv .tile__a.is-on{outline:3px solid var(--gold);outline-offset:5px}
.is-tv .tile__a:focus{outline:3px solid var(--gold);outline-offset:5px}
.is-tv .cbtn:focus{outline:3px solid var(--gold);outline-offset:4px}
.is-tv .shr__b:focus{outline:3px solid var(--gold);outline-offset:4px}
.is-tv .fbtn:focus{outline:3px solid var(--gold);outline-offset:4px}
.is-tv .link:focus{outline:3px solid var(--gold);outline-offset:5px}
.is-tv .gate__link:focus{outline:3px solid var(--gold);outline-offset:4px}
.is-tv .follow__admin a:focus{outline:3px solid var(--gold);outline-offset:4px}

@media (prefers-reduced-motion:reduce){
  /* The preview never starts at all under this (see STILL_ONLY in reels.js);
     these only cover the frame and the marks around it. .link > span is the
     arrow that slides away from the word on approach. */
  .tile__img,.tile__vid,.tile__edge,.tile__wait,.tile__t,.tile__no,.tile__still,
  .link,.link > span,.cbtn,.shr__b,.fbtn,.gate__link{transition:none}
  .link:hover > span{margin-right:10px}
  /* Two rules, not one list: Chrome 79 drops a list containing
     :focus-visible, and that would take the .is-on line with it. */
  .tile__a:hover .tile__img,.tile__a:focus-visible .tile__img{transform:scale(1.005)}
  .tile__a.is-on .tile__img{transform:scale(1.005)}
  .tile__a:active .tile__img,.tile__a:active .tile__edge{transition:none}
}

/* ---- a reel that is wider than the cell -------------------------------------
   The upload gate takes anything taller than it is wide, so 4:5 and 2:3 reels
   exist on this wall. object-fit:cover would cut a third off their sides to
   fill a 9:16 cell, so offShape() in reels.js hands those two the class and
   they are shown whole instead. Only the WIDER ones: a taller frame cropped
   top and bottom is what a vertical wall is supposed to look like.

   Two rules rather than one list, to match the rules above. Neither selector
   holds anything Chrome 79 cannot parse, so the hazard named over .tile__img
   does not apply here — this is consistency, not a constraint. */
.tile__still--fit .tile__img{object-fit:contain}
.tile__vid--fit{object-fit:contain}

/* The sort row at three metres, with the rest of this page's television type.
   10,5px on a wall TV is not small type, it is an absence of type. */
.is-tv .tbtn{font-size:17px}
.is-tv .rail__k{font-size:15px}
