/* attract screen: title, subtitle and the rule are defined ONCE in
   framework/kiosk.css now. The override that sat here made this station
   look different from its five neighbours for no reason anyone chose.
   Only the Devanagari line-height tuning stays local, because the strings
   differ. See the attract block in kiosk.css. */
/* Documentary Selector app-specific styles.
   15.6" ViewSonic TD1655, 1920x1080 LANDSCAPE. Builds on framework/kiosk.css. */

/* ==========================================================================
   [DS1] TYPE SIZE FOR THE SMALLEST PANEL IN THE GALLERY
   This station is a 15.6" 1920x1080 panel. The other landscape stations are
   32" at the same resolution, so a pixel here is 0.179 mm against their
   0.369 mm: identical CSS produces text at 49 percent of the physical size a
   visitor reads on the rest of the gallery floor. At the framework's 20px root
   that put the film titles at about 4.8 mm, which is a caption on a wall, not
   a menu, and it is why this screen tested as the hardest to read of the six.

   Re-base the root 1.8x. 36px here is 6.4 mm against 7.4 mm on a 32" panel at
   20px, i.e. 88 percent of the gallery's physical text size, and everything
   below (the grid, the detail column, the pill clearance) is sized against it.
   Deliberately app-local: this is the one station whose panel differs, and a
   millimetre scale threaded through the whole build a week before opening
   would put six working kiosks at risk to fix one.
   ========================================================================== */
/* This is the 15.6 inch selector, the ONLY panel a visitor stands right in
   front of; every other station is a 32 inch wall panel read from a metre or
   more, or a 22 inch portrait at arm's length. It had the largest type of the
   six (a 36px root against 20px elsewhere) which is exactly backwards: the
   smallest screen, closest to the eye, needs the smallest type, and at 36px
   the attract title and its button between them took two thirds of the panel.
   Sized now for roughly the same ANGULAR size as its siblings. */
html, body { font-size: clamp(16px, 1.05vw, 20px); }

/* ==========================================================================
   DEVANAGARI
   The framework bundles EB Garamond, Cormorant Garamond and Lato, and NONE of
   them carries a Devanagari glyph. Measured in real Chrome (canvas
   measureText, 64px, "हिंदी"): 'EB Garamond' and 'Lato' both give exactly
   100.41583251953125px, bit-identical to a deliberately non-existent family,
   while the same test on Latin text differs per family. Identical width means
   the browser never used those fonts for the Devanagari run; it fell through to
   whatever the machine happens to have.
   NOTE for anyone re-testing this: document.fonts.check('64px "EB Garamond"',
   'हिंदी') returns TRUE and is worthless here. Per spec it answers "can this
   text be rendered with available fonts", not "does this family cover it".
   The station is offline, and its font set is whatever setup-kiosk.sh's
   fonts-noto-core happens to install, so relying on system fallback would mean
   shipping a kiosk whose हिंदी button could come up as empty boxes after an
   image change. Noto Devanagari is therefore BUNDLED in framework/fonts/ (files
   added there; kiosk.css and kiosk.js are untouched) and declared here.
   ========================================================================== */
@font-face {
  font-family: 'Noto Sans Devanagari';
  src: url('../../framework/fonts/NotoSansDevanagari-Regular.ttf');
  font-weight: 400; font-style: normal; font-display: block;
}
@font-face {
  font-family: 'Noto Serif Devanagari';
  src: url('../../framework/fonts/NotoSerifDevanagari-Regular.ttf');
  font-weight: 400; font-style: normal; font-display: block;
}
/* Appended as a fallback after the framework faces, so Latin text is still set
   in Lato / EB Garamond exactly as before and only the Devanagari runs reach
   Noto. kiosk.css is not edited: these are the same custom properties,
   redefined in the app stylesheet that loads after it. */
:root {
  --serif: 'EB Garamond', 'Noto Serif Devanagari', serif;
  --display: 'Cormorant Garamond', 'Noto Serif Devanagari', serif;
  --sans: 'Lato', 'Noto Sans Devanagari', sans-serif;
}

/* ---------- inactive screens must be completely inert ----------
   framework/kiosk.css sets .screen { pointer-events: none } but then re-enables
   pointer-events on .grid, .card, .chip, button and .touchable. A child that
   re-enables pointer events is hit-testable even when its parent has them off,
   so the (opacity:0) chapter rows of #film sat on top of the right-hand film
   cards on #home and silently swallowed every tap there. Kill hit-testing on
   the whole subtree of any screen that is not active. Reported for a central
   fix in kiosk.css; this rule is the app-local guard. */
.screen:not(.active),
.screen:not(.active) * { pointer-events: none !important; }

/* ---------- touch targets ----------
   The app-local .chip and .langpill patches that used to sit here are gone:
   framework/kiosk.css now carries the 64px floor for both, so one number
   governs every small target on all six stations instead of three apps each
   guessing. The only thing left here is the cap that stops a long chapter
   name growing a chip across the whole screen. */
.chip { max-width: 30em; overflow: hidden; }

/* ---------- screensaver ----------
   The idle wallpaper is the SHARED canvas loom from framework/weave-saver.js,
   one consistent backdrop across all six gallery apps. This app's own animated
   CSS loom (panning wefts + gliding shuttle) is retired: the only remnant is a
   static warp texture kept as the no-JS fallback. It carries no animation (so
   it costs nothing) and sits BEFORE the canvas in the DOM, so on a working
   kiosk the canvas paints over it; nothing here may paint OVER the canvas. */
#saver .loom { position: absolute; inset: 0; overflow: hidden; }

#saver .warp {
  position: absolute; inset: 0;
  background: repeating-linear-gradient(90deg,
    rgba(201,162,75,.15) 0 2px, transparent 2px 26px);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 15%, #000 85%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 15%, #000 85%, transparent);
}

/* Both languages, always, one under the other. The stacking, the Devanagari
   face and the spacing between the pair all belong to framework/kiosk.css
   ([data-i18n-both]), so that all seven stations read identically; the only
   thing app-local here is how big this app's second line is. */

/* ==========================================================================
   [DS-SAVER-FIT] THE ATTRACT SCREEN IS CAPPED AGAINST THE PANEL, NOT THE ROOT

   This station runs a 1.8x root (36px, see DS1) because its panel is 15.6"
   rather than 32". The attract screen is the one screen that carries BOTH
   languages at once, so it stacks a two-line title, a two-line subtitle and a
   two-line touch prompt, and at 36px that already measured 1039 of the 1080
   pixels available. There were 41 pixels of slack.

   THAT 41px NO LONGER HOLDS, and the caps are kept anyway. The touch prompt
   was cut from "Touch to choose a film" to the single verb "Watch", so the
   overlay now measures 509px of 1080 at medium, with 286px of slack below it
   (434 of 768 and 167px of slack on a 1366x768 panel). Re-measured rather
   than assumed, because the reasoning below is written off the old figure.
   The caps are therefore no longer load-bearing at medium on either panel
   size. They stay because what they actually guard is the type-size control
   at large, which multiplies the root and is reachable from this very screen,
   and because nothing about a shorter prompt makes 1287px fit in 1080.

   The type-size control then multiplies the root by 1.24. Everything on this
   screen is em off that root, so large asked for 1287px in a 1080px panel:
   the overlay is centred, so it overflowed 104px at the top AND 104px at the
   bottom, which cut the ascenders off "Films of the Loom", pushed the title
   under the settings cluster, and took the bottom off the gold prompt (then
   the sentence "Touch to choose a film", now the verb "Watch"). That is the
   first screen a visitor meets, and the
   control that breaks it sits on that same screen, so a visitor can do this
   to themselves before they have touched anything else.

   The fix is the idiom this file already uses for the masthead and the
   now-playing screen: size against the viewport as well as the root and take
   whichever is smaller. At medium the em wins every time, so this screen is
   byte-for-byte what the fit and legibility audits signed off. At large the
   vh caps hold it inside the panel. The attract screen is already set in the
   largest type in the gallery (a 122px title against a 68px one everywhere
   else), so what a visitor loses by capping it is nothing they needed, and
   every screen BEHIND the attract still scales in full.

   The other five stations were measured at the same time and need no cap:
   the worst of them (archival) fills 1044 of 1920 at large.
   ========================================================================== */
#saver .overlay h1 { font-size: min(3.4em, 11.4vh); }
/* the shared small button in kiosk.css now applies here too */
/* The frame around the copy is em too, so it grew by 34px at large on its own
   and put Hindi back over the edge by 2px after the type was already capped.
   Padding is not reading matter, so it is capped the same way: 2em at medium
   is 72px and 6.7vh is 72.4px, which means this changes nothing until the
   root is pushed past its medium value. */
#saver .overlay { padding: min(2em, 6.7vh); }

/* ==========================================================================
   HOME: THE MASTHEAD
   The title and the instruction used to stack, which cost 60px of a 1080px
   panel and read as a heading barely a step above the card captions. They now
   share ONE baseline, so the title can be the display face at full title size
   (about 122px against the card title's 48px) inside the same header height
   the two small stacked lines took. Hierarchy comes from that gap, from the
   change of face and from the change of weight, not from a filled bar.
   ========================================================================== */
#home .topbar { padding-top: .42em; padding-bottom: .3em; align-items: flex-end; }
/* column-gap only. When the wall bridge is up the instruction is the longer of
   its two strings ("It plays on the big screen beside you"), and in Hindi at
   the large step that no longer fits beside the title, so the row wraps and the
   layout becomes the stacked one again. A row-gap on top of the title's own
   leading left the instruction floating in a band of nothing halfway down the
   screen; the leading below the title is already the space between them. */
#home .topbar .title { display: flex; align-items: baseline;
  column-gap: .9em; row-gap: 0; flex-wrap: wrap; min-width: 0; }
/* The masthead is capped in vh, so it is the one run of type on this screen
   that the size control does not grow. Same reasoning the framework used for
   sizing the settings cluster in vw: a visitor who presses "large" wants the
   CONTENT bigger, and letting the title grow with it takes 120px off a panel
   that has six films to show. 11.4vh is 123px on a 1080 panel, which is what
   3.4em already resolves to at the medium step, so medium and small are
   untouched and only large is held.
   Leading is tight for a display face set this large. Devanagari needs real
   leading or the matras above the शिरोरेखा are sheared off, so it gets its own
   value, measured rather than guessed (see [DEV-2]). 1.16 for Latin rather
   than something tighter: the strut of a run set in --display needs 1.185 of
   its own size in Latin and 1.52 in Devanagari, MEASURED on the live element
   rather than taken from the face's own metrics. Under those numbers the
   inline box overflows its line box, which is real layout overflow with matras
   sliced off, not merely tight. The values below clear both with a little on
   top. Anyone retuning these must re-measure in Hindi at the large step, which
   is the hardest case and the one a visitor who needs the control is in. */
#home .topbar h2 { font-size: min(3.4em, 11.4vh); line-height: 1.2; margin: 0; }
/* The Devanagari leading is needed for the marks above and below the letters,
   not for the space under the block, so the extra descent is taken back as a
   negative margin. The line box is still 1.56 and nothing is sheared; the
   title simply stops reserving 68px of empty air beneath itself on the one
   screen where that air costs a row of films. */
html[lang="hi"] #home .topbar h2 { line-height: 1.56; margin-bottom: -.15em; }
/* The one instruction. It is what tells a standing visitor what this screen is
   for, so it reads at body size, but it is now plainly subordinate to the
   title rather than a second line of the same importance.
   Floored, same idiom as the card eyebrow: .82em of the [DS1] root computed
   16.4px at 1920x1080 and 13.1px on a 1366x768 panel, both under the 18px
   gallery reading floor (HOUSE-STYLE.md), on the sentence the whole screen
   depends on. The max() nails the minimum at every panel size and the em is
   still what grows it at the large type step. Measured after: 18px at both
   panel sizes at medium. */
.topbar .title .lede { font-family: var(--sans); font-weight: 300;
  font-size: max(18px, .82em); color: var(--ink-dim); margin: 0; }

/* which language is on the wall right now (a label, not a control) */
.langbadge { display: inline-flex; align-items: center; padding: .3em 1.2em;
             border-radius: 999px; border: 1px solid var(--ink-faint);
             color: var(--ink-dim); font-family: var(--sans); font-size: 1em; }
.langbadge:empty { display: none; }

/* ==========================================================================
   THE POSTER WALL
   Three across and two down for the six delivered films, so the whole
   programme is on one screen and nothing hides below a fold. app.js widens
   this to four columns if a later manifest carries more than six films.

   The rows SHARE the panel (minmax(0,1fr)) instead of each taking the height
   of its own contents. That is the change that makes this screen fill a 1920 x
   1080 panel at every type size in both languages: the card is a fixed box
   that the grid hands out, and the type inside it grows and shrinks without
   moving anything. The old arrangement sized each card from its title and its
   caption, so Hindi at the large type step pushed the second row 70px off the
   bottom of the panel, and English at medium left 107px of dead space under it.
   Measured after: nothing to scroll and no dead band, in both languages at all
   three type steps.
   ========================================================================== */
.filmgrid { grid-template-columns: repeat(var(--cols, 3), 1fr);
  grid-auto-rows: minmax(0, 1fr); align-content: stretch;
  overflow: hidden;                    /* six films fit; there is nothing to scroll to */
}

/* The picture IS the card: it fills the tile edge to edge and the type is set
   over the foot of it. The filled caption bar that used to sit underneath is
   what made a gallery of textiles look like a list of database rows. */
.filmgrid .card { position: relative; min-height: 0; border-color: transparent;
  background: #191510; box-shadow: 0 10px 26px rgba(0, 0, 0, .45); }
/* The "no films in the manifest" card. It is the only card that is ever alone
   in the grid, and a lone tile in a three-column track is a tall narrow strip.
   Let it span the row and cap its height so it reads as a woven panel with a
   sentence on it, which is what a visitor should meet when a station's content
   has not arrived. */
.filmgrid .card.nofilms { grid-column: 1 / -1; max-height: 46vh; }
/* The press affordance has to come back as something other than a border,
   because there is no visible border to light up any more. An inset ring adds
   no geometry, so nothing reflows under the finger. */
.filmgrid .card:active { border-color: transparent;
  box-shadow: inset 0 0 0 4px var(--gold), 0 10px 26px rgba(0, 0, 0, .45); }

.card .thumbwrap { position: relative; }
.filmgrid .card .thumbwrap { position: absolute; inset: 0; overflow: hidden; }
.card .thumbwrap .thumb { width: 100%; aspect-ratio: 16/9; object-fit: cover;
  background: #000; display: block; }
/* aspect-ratio is deliberately dropped here: the tile decides the shape and the
   still (or the woven cloth) is cropped to fill it. */
.filmgrid .card .thumbwrap .thumb { width: 100%; height: 100%; aspect-ratio: auto; }

/* The scrim. Cloth and film stills are both high-frequency and mid-value, so
   white type over a bare picture is legible on one card and not on the next.
   This is a gradient over the picture rather than a bar beside it, so the
   image still runs to all four edges of the tile.
   Measured on the darkest step of the ramp: --ink 13.9:1, --gold 7.2:1. */
.filmgrid .card .thumbwrap::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
    rgba(14, 11, 8, .96) 0%, rgba(14, 11, 8, .92) 24%, rgba(14, 11, 8, .62) 44%,
    rgba(14, 11, 8, .22) 64%, rgba(14, 11, 8, 0) 84%);
}

/* The coming-soon banner is a REAL element rather than a ::after with a hard
   coded string: CSS `content` cannot go through Kiosk.t(), and a second copy of
   the wording living in the stylesheet would drift from the dictionary. app.js
   renders <span class="comingribbon"> and re-renders it on a language switch. */
.card.coming .thumbwrap .comingribbon {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(22,19,15,.72); color: var(--gold);
  font-family: var(--sans); font-size: .85em; letter-spacing: .18em;
}

/* The two lines of type, over the foot of the picture. margin-top:auto is what
   holds them there: .card is a column flex box (kiosk.css) and .thumbwrap is
   out of flow, so .meta is the only item and the auto margin pushes it down. */
/* text-align is stated because .card is a <button>, and the user agent centres
   the text inside one. A centred caption under a centred caption is what a
   default component looks like; a poster's title is ranged left. */
.filmgrid .card .meta { position: relative; z-index: 1; margin-top: auto;
  display: flex; flex-direction: column; align-items: flex-start;
  text-align: left; min-width: 0; padding: .9em 1em 1em; }

/* long, unbroken words in manifest copy must never widen or escape a card */
.card .meta h3 { overflow-wrap: anywhere; }
.card .meta .caption { overflow-wrap: anywhere; }

/* The film's name, and the loudest thing on the tile after the picture.
   line-height 1.26 and not tighter: EB Garamond's content area is about 1.15em
   and a -webkit-box with a line-height under that overflows its own line box,
   which Chrome reports as real layout overflow (scrollHeight > clientHeight) on
   a title that is not visually cut at all. testing/test_documentary_selector.py
   asserts nothing on a card is truncated by exactly that measurement, so a
   tighter setting here fails the suite as well as shaving the type. */
.filmgrid .card .meta h3 { margin: 0; font-size: 1.32em; line-height: 1.26;
  color: var(--ink); text-shadow: 0 2px 18px rgba(0, 0, 0, .9), 0 1px 3px rgba(0, 0, 0, .8); }

/* "16 MIN · BIHAR" moves ABOVE the title and becomes the framework's eyebrow:
   a small tracked gold cap line, which is where a duration and a place belong
   on a poster. It is still the same element and the same text in the same
   order (the tests read it as `.card .caption`), only ordered and set
   differently. `order` rather than a markup change, because the reading order
   for anything walking the DOM should stay title-then-detail. */
.filmgrid .card .meta .caption { order: -1; margin: 0 0 .3em;
  font-family: var(--sans); font-weight: 700; font-size: max(20px, .58em);
  letter-spacing: .15em; text-transform: uppercase; color: var(--gold);
  text-shadow: 0 1px 10px rgba(0, 0, 0, .95); }

/* ==========================================================================
   FILM DETAIL
   The poster used to be a small framed picture at the top of a 40% column with
   the page laid out around it, and the screen carried two empty bands: the
   bottom of the poster column and, under a one-chapter film, most of the
   chapter column. The poster is now the left half of the screen, top to bottom
   and edge to edge, with the film's name, its facts and its one action set
   over the foot of it on a gradient. Nothing is framed, nothing is centred in
   a band of nothing, and the picture is doing the work a picture should do at
   a metre's reading distance.
   padding-top on both columns clears the back button, which the framework pins
   to top:1em. It grew with the [DS1] root, so the clearance is in em.
   ========================================================================== */
.detail { flex: 1; display: flex; gap: 0; padding: 0; overflow: hidden;
  position: relative; z-index: 1; }

/* Woven cloth behind the reading column, masked so it is texture at the far
   edge and flat ground under the text. Pure decoration: it never takes a
   touch, and it sits under everything. */
/* opacity .2 against a veil of .72, and both numbers were chosen on the LOUDEST
   cloth this renderer makes, not the quietest. At .5 a maheshwari read as fine
   horizontal texture and looked right, while a kanchipuram temple border in the
   same slot put hard gold and navy triangles straight through the chapter list.
   Cloth here is a surface, not a picture: a visitor should feel the column is
   woven without ever noticing it while reading. */
#film .clothback { position: absolute; inset: 0 0 0 42%; z-index: 0;
  pointer-events: none; opacity: .2;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22%);
          mask-image: linear-gradient(to right, transparent 0, #000 22%);
}

.detail .hero { flex: 0 0 42%; position: relative; min-width: 0; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-end; gap: .28em;
  padding: 4.4em 2.1em 1.9em; }
/* Everything the visitor reads sits above the poster and above its scrim.
   The poster itself is taken back OUT of flow on the next line, and it has to
   out-specify this rule to do it, hence the full path. */
.detail .hero > * { position: relative; z-index: 1; }
.detail .hero .dthumb { position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover;
  border: 0; border-radius: 0; background: #000; }
/* Two ramps. Up the picture, so the type at the foot has ground under it. And
   off its right edge into the page, so the poster dissolves into the reading
   column instead of ending on a hard vertical seam down the middle of a
   1920px panel. */
.detail .hero::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    linear-gradient(to top, rgba(14, 11, 8, .97) 0%, rgba(14, 11, 8, .93) 30%,
      rgba(14, 11, 8, .66) 52%, rgba(14, 11, 8, .24) 74%, rgba(14, 11, 8, .02) 100%),
    linear-gradient(to right, rgba(22, 19, 15, .35) 0%, rgba(22, 19, 15, 0) 20%,
      rgba(22, 19, 15, 0) 42%, rgba(22, 19, 15, .82) 88%, rgba(22, 19, 15, 1) 99%);
}

/* Order on the hero, top to bottom: the facts as an eyebrow, then the title,
   then the credit, then the one action. The facts line leads because it is a
   label for the title under it, which is how a wall caption is set. */
.detail .hero #dmeta   { order: 1; }
.detail .hero h1       { order: 2; }
.detail .hero #dcredit { order: 3; }
.detail .hero .btn.big { order: 4; }

/* Line-height stated, in both scripts, for the reason set out on the masthead:
   kiosk.css sets h1 to 1.06, which is under the 1.185 a Latin run in --display
   actually needs and well under the 1.52 a Devanagari one does, so the film's
   name overflowed its own line box on every screen of this app. Measured on
   the live element at both type extremes. */
/* Capped in vh as well, for the reason the masthead is. The hero is a column
   anchored to the foot of the poster, and a flex column that runs out of room
   SHRINKS its items rather than spilling them, so at the large step a
   three-line Hindi title was quietly squeezed inside its own line boxes and
   sheared its matras. 8vh is 86px on a 1080 panel, which is what 2.4em already
   resolves to at medium, so only the large step is held. */
.detail .hero h1 { font-size: min(2.4em, 8vh); line-height: 1.2; }
html[lang="hi"] .detail .hero h1 { line-height: 1.56; }
html[lang="hi"] #dcredit { line-height: 1.6; }
/* The facts line: place, tradition, running time, language. Gold and tracked
   so it reads as a label rather than as a second, quieter title. */
/* line-height is stated because this line runs to two lines in English on the
   longest film ("Madhya Pradesh · Saree Traditions · 17 min · English"), and
   at the inherited body leading the two lines of small caps collided. */
#dmeta { font-family: var(--sans); font-weight: 700; letter-spacing: .14em;
  line-height: 1.55; text-transform: uppercase; color: var(--gold);
  margin-bottom: .18em; text-shadow: 0 1px 10px rgba(0, 0, 0, .95); }
/* justify-content:flex-end already holds the column at the foot of the poster,
   so the old `margin-top:auto` here would fight it: an auto margin eats the
   free space and pushes everything else back to the top. A plain margin.

   The type comes DOWN from 1.25em (45px on the [DS1] root) to 1.02em, and the
   target does not: min-height holds the framework's 64px floor and the padding
   puts the real hit box at about 95px. That is the whole trick this screen was
   missing. A control can be quiet and still be easy to hit, because padding is
   invisible; the thing that read as a "big button" was 45px of type in a solid
   gold slab, not the size of the area a finger has to land in. */
.detail .hero .btn.big { margin-top: .75em; align-self: flex-start; flex: 0 0 auto;
  font-size: 1.02em; padding: .8em 1.7em; min-height: var(--touch); }
/* Post-opening fix (17 Aug): the framework's 26%-opacity HH ghost watermark
   (.brand-watermarks .wm-hh, bottom-left, fixed) measured at x:14-144px,
   y:976-1068px on a 1920x1080 panel, and this button measured at x:42-343px,
   y:978-1042px in the same corner - a ~102px horizontal overlap with almost
   the button's full height. The watermark is shared, fixed-position chrome
   across all six apps (kiosk.css), so it is not the thing to move for one
   screen; only this screen's button seat needed to lift clear. margin-bottom
   moves the button (and, via the flex column's justify-content:flex-end, the
   whole stack above it) up by the same amount without touching horizontal
   alignment, so it stays seated under the title/credit exactly as before. */
.detail .hero .btn.big { margin-bottom: 4.3em; }
.detail .hero .btn.big.primary { box-shadow: 0 8px 26px rgba(0, 0, 0, .5); }
.detail .hero .btn.big.coming { border-color: var(--ink-faint); color: var(--ink-faint);
  background: rgba(14, 11, 8, .72); }
#dcredit { color: var(--ink-dim); text-shadow: 0 1px 10px rgba(0, 0, 0, .9); }
#dcredit:empty { display: none; }

/* overlong manifest copy must clip inside its column, never push the Play
   button off screen or run across the chapter column. The clamps are set well
   past anything the delivered manifest contains (the longest synopsis runs to
   six lines in Hindi against a limit of ten), so they only ever fire on a
   hand-edited mistake, and a visitor who wants the rest of a clamped title has
   the film screen it came from. */
.detail .hero { overflow: hidden; }
#dtitle, #dmeta, #ddesc { overflow-wrap: anywhere; }
#dtitle { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; }
#dmeta { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
#dcredit { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
/* The synopsis sits at the head of the wider column, where the whole of it is
   read at one glance rather than clipped into a narrow measure beside the
   poster. It carries the height the poster column no longer wastes, so it is
   set larger and with more leading: this is the curator's own writing and it
   is the only continuous prose on the station. */
/* Capped in vh for the same reason the masthead is: at 1080px 3.7vh is 40px,
   which is exactly what 1.1em resolves to at the medium step, so the cap only
   bites at large and only to keep the chapter list under it on the panel. */
#ddesc { font-size: min(1.1em, 3.7vh); line-height: 1.72; flex: 0 0 auto; margin-bottom: 1.1em;
  display: -webkit-box; -webkit-line-clamp: 10; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 0; }

.detail .chapters { flex: 1; display: flex; flex-direction: column;
  min-width: 0; min-height: 0; padding: 4.4em 2.4em 1.9em 2.4em; }
/* "The film" / "Chapters" is a section label, not a second title. It was set
   at h2 (74px on the [DS1] root), which put it in the same weight class as the
   film's own name across the gutter and flattened the hierarchy this screen
   is supposed to have: title, then the curator's words, then the list. */
.detail .chapters #chaphead { font-family: var(--sans); font-weight: 700;
  font-size: max(20px, .62em); letter-spacing: .14em; text-transform: uppercase;
  color: var(--gold); line-height: 1.3; }
.cliplist { flex: 1; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: .8em; padding-bottom: .2em; }
.cliplist::-webkit-scrollbar { width: 0; }

.cliprow {
  display: flex; align-items: center; gap: 1.1em; text-align: left;
  min-height: var(--touch); padding: .95em 1.25em;
  background: rgba(237, 229, 216, .05); border: 1px solid rgba(237, 229, 216, .09);
  border-radius: var(--radius);
  color: var(--ink); font-family: var(--sans); font-size: 1em; pointer-events: auto;
}
/* An uncut documentary has exactly one row, and a 64px row stranded at the top
   of a 600px column is what the empty band on this screen actually was. When
   it is the only one, it grows into the space and becomes the large, obvious
   thing to press, with its number and its play mark scaled to match so the
   panel is filled rather than hollow. Capped, so it stays a row and does not
   become a wall. All six delivered films take this path. */
.cliplist .cliprow:first-child:last-child { flex: 1 1 auto; max-height: 26vh; }
.cliplist .cliprow:first-child:last-child .num { flex: 0 0 66px; height: 66px;
  font-size: 1.5em; }
.cliplist .cliprow:first-child:last-child .go { font-size: 2em; }
.cliprow:active { border-color: var(--gold); transform: scale(.99); }
.cliprow .num {
  flex: 0 0 52px; height: 52px; border-radius: 50%;
  border: 1.5px solid var(--gold); color: var(--gold);
  font-family: var(--serif); font-size: 1.25em;
  display: flex; align-items: center; justify-content: center;
}
.cliprow .ct { flex: 1; min-width: 0; }
.cliprow .ct h3 { font-size: 1.2em; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cliprow .ct .caption { margin-top: .15em; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.cliplist .empty { color: var(--ink-faint); font-family: var(--sans); padding: 1.2em .2em; }
.cliprow .go { color: var(--gold); font-size: 1.4em; }
.cliprow.off { opacity: .45; }
.cliprow.off .num { border-color: var(--ink-faint); color: var(--ink-faint); }
.cliprow.off .go { visibility: hidden; }

/* ---------- now playing ----------
   The whole column is spent at the [DS1] type size: with a four-chapter film
   it ran 1122px tall in English and 1224px in Hindi inside a 1080px panel, and
   "Return to menu" fell off the bottom, which is the one control on the screen
   a visitor needs. The height comes back out of the spacing between the parts
   and out of the headline, not out of the transport buttons, which are what
   the visitor is aiming at. Measured after: 940px English, 1040px Hindi. */
#playing { align-items: center; justify-content: center; }
.playwrap { width: min(1100px, 86vw); display: flex; flex-direction: column;
  align-items: center; text-align: center; gap: .5em; }
/* Every large run on this column is capped in vh as well as sized in em.
   The column is the one screen in the app whose height is fully spent, and at
   the large type step in Hindi it ran 1088px inside a 1080px panel: "Return to
   menu", the only control a visitor on this screen needs, fell off the bottom.
   The caps bite ONLY at the large step (at 1080px, 6vh is 65px against the
   66px that 2.2em resolves to at medium), so small and medium are exactly what
   the fit audit signed off. The transport buttons keep their full size,
   because they are what the visitor is aiming at; the height comes out of the
   headline and the chapter line, which they are only reading. */
.playwrap h1 { font-size: min(2.2em, 6vh); line-height: 1.2; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.playwrap .weave-rule { margin: .3em 0; }
.playwrap #pclip { font-size: min(2.05em, 5.4vh); line-height: 1.3; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
html[lang="hi"] .playwrap h1 { line-height: 1.56; }
html[lang="hi"] .playwrap #pclip { line-height: 1.6; }
.playwrap #pmode { font-size: min(.95em, 2.6vh); }
.playwrap .langbadge { font-size: min(1em, 2.7vh); }
.playwrap .prog-row .time { font-size: min(1em, 2.7vh); }
#playing .btn.ghost { font-size: min(1.15em, 3vh); }
.chapchips { max-height: 22vh; overflow: hidden; }
.playwrap .weave-rule { width: 60%; }

.prog-row { display: flex; align-items: center; gap: 1.2em; width: 100%; }
.wallprog { flex: 1; height: 10px; border-radius: 5px; background: #3a332a; overflow: hidden; }
.wallprog .fill { height: 100%; width: 0%; background: var(--gold);
  border-radius: 5px; transition: width 1.6s linear; }
.prog-row .time { font-family: var(--sans); font-size: 1em; color: var(--ink-dim);
  min-width: 4.5em; }

.pcontrols { display: flex; gap: 2em; margin: .2em 0; }
/* The transport buttons are a fixed 96px, so their GLYPHS must be fixed too.
   At 1.9em on the [DS1] root the restart arrow drew 68px tall inside a 94px
   circle and spilled 4px out of it, and the pause bars spilled 10px sideways;
   at the large type step the em sizing took the glyph to 85px in the same
   96px circle. A cap in px, and line-height 1 so the glyph's own leading
   cannot push it out either. The TARGET is untouched at 96px. */
.pbtn.xl { width: 96px; height: 96px; font-size: min(1.9em, 50px); line-height: 1; }

.chapchips { justify-content: center; }
#playing .btn.ghost { margin-top: .25em; }

/* The local seek-bar enlargement that used to live here has been removed:
   kiosk.css now builds the bar as a proper 64px target (content-box, 8px of
   visible rail). Re-adding a height here would fight that and produce a
   112px bar. */

/* ---------- toast ---------- */
#toast {
  position: fixed; left: 50%; bottom: 56px; transform: translateX(-50%) translateY(20px);
  max-width: 70vw; padding: 1em 1.8em; border-radius: var(--radius);
  background: var(--bg-raised); border: 1px solid var(--gold); color: var(--ink);
  font-family: var(--sans); font-size: 1.05em; text-align: center;
  opacity: 0; pointer-events: none; transition: opacity .35s, transform .35s; z-index: 200;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }


/* ── escape & abuse hardening (Aug 2026 abuse pass) ───────────────────────────
   Gestures must stay inside the app. `touch-action: manipulation` (kiosk.css)
   still lets Chromium claim a two-finger pinch as a browser zoom: reproduced at
   visualViewport.scale = 4 in testing/test_escape.py, and NOT stopped by the
   --disable-pinch launch flag. Pinning the full-screen layers to
   `touch-action: none` and re-granting only the axis each scroller needs is what
   actually holds. Chrome stops the touch-action walk at the scroller, so
   `none` on the .screen does not disable `pan-y` inside it (measured).
   `overscroll-behavior: none` stops the two-finger overscroll back/forward
   navigation without relying on --overscroll-history-navigation=0. */
html, body { overscroll-behavior: none; }
img, video, svg { -webkit-user-drag: none; user-drag: none; }
#saver, .screen, .player { touch-action: none; }
.grid, .cliplist { touch-action: pan-y; }

/* ==========================================================================
   GALLERY LEGIBILITY AUDIT (app-local corrections)
   Panel: 15.6" 1920x1080 landscape, visitors standing 40-80 cm away.
   Measured with testing/test_visual_audit.py + test_contrast_audit.py.
   ========================================================================== */

/* [VIS-1] Every film card is a <button class="card">, and kiosk.css never
   resets the user-agent `font: 400 13.333px Arial` on buttons. The card
   therefore ran at 13.3px instead of the 20px document size, and everything
   inside it inherited from that: title 18px (meant to be 27px), synopsis
   11.7px, the "4 chapters · Weaving Techniques" line 10.9px. Unreadable at
   gallery distance. Re-inherit the document font.
   Reported upstream, since kiosk.css should carry `button { font: inherit }`. */
.card { font: inherit; }

/* [VIS-2] `.chip` in kiosk.css sets a border and a text colour but no
   background, so an unselected chip is painted with the UA `buttonface` fill.
   Measured: --ink-dim #b3a895 on rgb(239,239,239) = 2.04:1, and three
   near-white pills out-shouted the film grid they filter. Reported upstream. */
.chip { background: transparent; }
.chip.on { background: rgba(201, 162, 75, .08); }

/* [VIS-3] The "content coming soon" scrim was a full-cover centred label at
   72% alpha, so it landed exactly on the artwork's own title: "Banaras" /
   CONTENT COMING SOON / "The Eternal Warp" stacked into one illegible knot.
   It became a ribbon along the FOOT of the thumbnail, which was right while
   the caption lived in a bar underneath. The caption is now set over the foot
   of the picture itself, so the ribbon moves to the head of the tile and
   becomes a tag: a small solid object in the one corner nothing else uses,
   which is also where a visitor's eye enters the card. */
.card.coming .thumbwrap .comingribbon {
  inset: .7em auto auto .7em; height: auto; width: auto;
  display: inline-flex; padding: .42em .95em; border-radius: 999px;
  background: rgba(14, 11, 8, .9);
  border: 1px solid rgba(201, 162, 75, .5);
  color: var(--gold);
  font-size: max(18px, .56em); letter-spacing: .14em;
}

/* [VIS-4] Gallery reading floor is ~18px rendered. These are app-owned text
   runs that fell under it once VIS-1 was in place, or that carry --ink-faint
   (3.15:1 on --bg-card, 3.84:1 on --bg, both under AA body 4.5:1). */
/* `grid-auto-rows: max-content` used to be pinned here, because `.grid` is
   `flex: 1; overflow-y: auto` and `.card` is `overflow: hidden`, so grid's
   "maximise tracks" step grew both auto rows equally and the card clipped its
   own last line (measured scrollHeight 437 in clientHeight 407). That fix
   belonged to a card whose height came from its own text.
   It is deliberately gone. The card is now a fixed tile with the caption set
   OVER the picture, so equal rows filling the viewport is exactly what is
   wanted, and it is what makes the grid fill the panel at every type size.
   `minmax(0, 1fr)` (in the POSTER WALL block above) is the safe spelling:
   plain `1fr` is `minmax(auto, 1fr)`, whose auto minimum would let a long
   Hindi title at the large step push a row taller than its share again. */

/* The eyebrow line ("16 MIN · BIHAR") and the gallery reading floor. .58em
   resolves to ~21px today; the max() nails the minimum so a future change to
   the [DS1] root cannot quietly drop it under the floor. The floor is stated
   in the POSTER WALL block where the line is styled, so it lives with the
   rest of that rule rather than being contradicted from two places. */
.card .meta .caption { font-size: max(22px, .9em); color: var(--ink-dim); }

/* [FIT-1] is retired. It bought the height for a second row of cards out of
   the thumbnail (a 16/9 frame cropped to a 2.75/1 letterbox) and out of the
   caption bar's padding, because a card was as tall as its contents made it
   and the six had to land inside 1080px. A card no longer has a content
   height: the grid gives every tile the same share of the panel and the
   picture fills whatever it is given. So the letterbox crop goes, the padding
   goes back to something a poster caption deserves, and the two Hindi-only
   counterparts in [DEV-3] go with them. Measured at 1920x1080 in both
   languages at all three type steps: nothing to scroll and no dead band. */
.filmgrid { gap: .62em; padding: .1em .9em .9em; }

/* [FIT-2] Card height must not depend on how long a curator makes a title.
   An over-long title is a content mistake, and the kiosk absorbs it by
   bounding the card rather than by pushing the second row off the screen; the
   film's own screen carries the title in full, so nothing is lost to a
   visitor who taps it. Two lines is past every delivered title. */
.filmgrid .card .meta h3,
.filmgrid .card .meta .caption {
  display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden;
}
.filmgrid .card .meta h3 { -webkit-line-clamp: 2; }
/* An over-long region name in a hand-edited manifest is the last unbounded
   element on the card. */
.filmgrid .card .meta .caption { -webkit-line-clamp: 1; }

.cliprow .ct .caption { font-size: .95em; color: var(--ink-dim); }
/* The facts line is set as an eyebrow (see FILM DETAIL above), so it is
   smaller and gold rather than body-sized and dim. The 20px floor keeps it
   above the gallery reading floor whatever happens to the [DS1] root. */
#dmeta { font-size: clamp(20px, .62em, 2.4vh); }
/* The film maker's credit. It belongs on the film and it has to be readable,
   but it is the last line in the hero's order of importance and was reading at
   nearly the size of the facts line above the title. Both lines carry a vh
   ceiling as well as the 20px floor, so the hero column cannot be pushed into
   shrinking its own type at the large step. */
#dcredit { font-size: clamp(20px, .78em, 2.9vh); }
#saver .overlay .caption { font-size: .95em; color: var(--ink-dim); }

/* [VIS-5] retired with the CSS shuttle: the shared weave-saver canvas keeps
   its own shuttle in the lower half and dims the centre with a vignette, so
   the saver copy stays clear without an app-side override. */


/* ==========================================================================
   TOP-LEFT CHROME CLEARANCE
   framework/kiosk.css pins the settings cluster (the language toggle AND, now,
   the type-size control) to `position: fixed; top: 1em; left: 1em` on EVERY
   screen including the screensaver. Two things in this app start in that exact
   corner and were being covered by it:

     * #home .topbar. kiosk.css pads it 1.6em, so the menu title began at x=32,
       straight under the chrome and unreadable behind it.
     * #film .backbtn. kiosk.css puts .backbtn at top:1em; left:1em, z-index 40,
       i.e. underneath the cluster and completely unhittable. A visitor on a
       film page had no "All films" button at all: they hit हिंदी instead.

   Both are corrected by indenting past the cluster rather than by moving it,
   because its whole point is that it is in the same place on all six kiosks
   and is learned once.
   testing/test_documentary_selector.py asserts the clearance on every screen,
   so a future framework change to the chrome fails loudly instead of quietly
   burying a control.

   The number comes from the framework, which measures its own chrome and
   republishes --kiosk-chrome-clear on boot, after the Devanagari faces load,
   and on every language or type-size change. This app used to measure it
   itself into a private --langpill-clear; that measured the language pill
   alone, which is now about half the cluster, and the two writers raced. The
   local fallback below is only for the single frame before the framework's
   first measurement lands. (A length, not `14em`: `left` in em would resolve
   against the BUTTON's own font-size and land somewhere else entirely.) */
#home .topbar { padding-left: var(--kiosk-chrome-clear, 451px); }
#film .backbtn { left: var(--kiosk-chrome-clear, 451px); }
/* The back button now sits on a photograph rather than on the page ground, so
   it needs a ground of its own to stay legible. It is also quieter than the
   framework default: 30px of type in a hairline instead of 41px in a heavy
   gold outline, because on this screen it is the way back, not the thing to
   do. min-height keeps the target on the framework's 64px floor whatever the
   type does, and the measured box is about 74 x 200. :active has to be
   restated because this selector carries an id and would otherwise outrank
   .btn:active. The label is floored at 18px: .84em of the [DS1] root computed
   16.8px at 1920x1080 (13.4px at 1366x768), under the gallery reading floor
   for the one control that gets a visitor off this screen. Quieter than the
   framework default is still the intent; the max() only holds the floor and
   the em keeps it scaling at the large type step. */
#film .backbtn { background: rgba(14, 11, 8, .78); font-size: max(18px, .84em);
  padding: .55em 1.3em; min-height: var(--touch);
  border-color: rgba(201, 162, 75, .45); letter-spacing: .06em; }
#film .backbtn:active { background: var(--gold); color: var(--bg); }
/* the chevron is decoration; the word beside it is what data-i18n swaps */
.btn .glyph { line-height: 1; }

/* The app-local rule that lifted the pill above the screensaver has been
   deleted: framework/kiosk.css now gives .langpill a z-index above #saver for
   every app at once, which is right, because a Hindi-first visitor walks up to
   an idle station on all six of them. */

/* ==========================================================================
   DEVANAGARI LAYOUT
   Hindi is not simply "the same screen with other words in it": Devanagari sets
   taller (matras sit above the शिरोरेखा and below the baseline) and several of
   these strings are longer than their English source. Everything in this block
   is scoped to html[lang="hi"], so the English screens are byte-for-byte what
   the legibility and fit audits above signed off.
   ========================================================================== */

/* [DEV-1] Letter-spacing is a Latin small-caps device. Applied to Devanagari it
   pulls the शिरोरेखा apart between characters and breaks conjuncts visually.
   The worst offender was the coming-soon ribbon at .16em. Every tracked run in
   this app is reset for Hindi. */
html[lang="hi"] .caption,
html[lang="hi"] .btn,
html[lang="hi"] .homepill,
html[lang="hi"] .card.coming .thumbwrap .comingribbon { letter-spacing: normal; }
/* The two eyebrow lines added with the poster wall are tracked hard (.15em and
   .14em), and both out-specify the reset above, so they have to be named. This
   is the same rule, not a new one: no Devanagari run in this app is tracked. */
html[lang="hi"] .filmgrid .card .meta .caption,
html[lang="hi"] .detail .chapters #chaphead,
html[lang="hi"] #film .backbtn,
html[lang="hi"] #dmeta { letter-spacing: normal; }

/* [DEV-2] Line-height. kiosk.css sets h1 1.15 and h2 1.25, tuned for Garamond,
   whose ink sits between baseline and cap height. Devanagari does not: matras
   hang above the शिरोरेखा (ि ी े ै ो ौ ं) and below the baseline (ु ू ृ), and
   Noto Devanagari declares metrics to match, and its ascent+descent measures
   ~1.47em for the sans face and ~1.53em for the serif, against EB Garamond's
   ~1.15em.

   That is not merely a matter of taste: when the font's content area is taller
   than the line-height, the inline box overflows its own line box and Chrome
   reports real layout overflow, with matras sliced off rather than just tight.
   Measured on the saver headline (Noto Serif Devanagari, 64px): scrollHeight
   94 in a clientHeight of 90 at line-height 1.4, and still 98 in 96 at 1.5;
   the chapter heading gave 57 in 55 at 1.45. The values below clear the serif
   face's 1.53 with real leading on top, rather than sitting on the boundary
   where the next font revision would break them again.

   The -webkit-line-clamp blocks elsewhere inherit this, so the clamps still
   bound the same NUMBER of lines; they are just taller lines, which is what
   the grid maths in [DEV-3] pays for. */
html[lang="hi"] h1, html[lang="hi"] .h1 { line-height: 1.6; }
html[lang="hi"] h2, html[lang="hi"] .h2 { line-height: 1.6; }
html[lang="hi"] h3, html[lang="hi"] .h3 { line-height: 1.6; }
html[lang="hi"] .body { line-height: 1.85; }
html[lang="hi"] .cliprow .ct .caption,
html[lang="hi"] .card .meta .caption { line-height: 1.6; }

/* [DEV-8] THE SCREENSAVER IS THE CASE html[lang] CANNOT COVER.
   Every rule above keys off the INTERFACE language, which is right everywhere
   a screen shows one script at a time. The saver shows both at once and always
   does, on purpose: a Hindi-first visitor walking up to an idle station must
   not have to press anything to see their own language. So the Devanagari line
   is on the glass even while the kiosk is set to English, where none of the
   html[lang="hi"] rules reach it, and the Latin line is on the glass while the
   kiosk is set to Hindi, where they reach it and give it Devanagari leading it
   does not need.

   Both were wrong, measured on the live spans at every type step:
     * the Devanagari span had 1.4 (from kiosk.css's own [data-i18n-both] rule)
       and overflowed by 10px, so its matras sheared in BOTH interface
       languages;
     * the Cormorant span inherited h1's 1.06 and overflowed by 8px, so the
       English title sheared whenever the kiosk was in English, which is how it
       stands for most of its life.
   The values below were found by raising the leading and re-measuring until
   the overflow reached zero, not by dividing the reported content height by
   the font size: on a block whose family list spans two scripts the reported
   height moves with the line-height, so one round of arithmetic lands short.

   Leading here therefore follows the SCRIPT, not the toggle, which is the only
   thing that can be correct on a block that paints both. testing asserts this
   screen carries no clipped Hindi, so a future change to either face fails
   loudly. The saver column is measured after: it fits inside 1080px in both
   languages at all three type steps. */
#saver [data-i18n-both] > [lang="hi"] { line-height: 1.62; }
#saver h1[data-i18n-both] > [lang="en"] { line-height: 1.3; }

/* [DEV-3] is retired with [FIT-1]. It shaved the thumbnail and the meta
   padding a second time for Hindi, because taller Devanagari lines made a
   content-sized card taller and pushed row 2 over the edge of the panel. A
   tile is no longer sized by its contents, so the whole class of bug is gone
   and there is nothing left to shave. What Hindi still needs on this screen is
   only leading, which [DEV-2] gives it, and a slightly tighter title, because
   Devanagari at 1.6 leading over two lines is a lot of ink inside a fixed
   tile. Measured at 1920x1080, Hindi, large: both rows inside the panel with
   nothing to scroll and nothing clipped. */
/* This override exists because the card title rule above out-specifies
   [DEV-2]'s `html[lang="hi"] h3` (three classes and a type against one
   attribute and two types), so without it a Hindi card would be set at the
   Latin leading and shear its matras. 1.58 and not lower: measured on the live
   card at the large step, a Devanagari title in --serif needs 1.53 of its own
   size before the marks above the शिरोरेखा are inside the line box. */
html[lang="hi"] .filmgrid .card .meta h3 { line-height: 1.58; }
html[lang="hi"] .filmgrid .card .meta { padding: .7em 1em .85em; }

/* [DEV-4] deliberately not written. The now-playing stack was the obvious
   candidate for a Hindi-only tightening, but it does not need one: measured at
   1920x1080 with a four-chapter film, the .playwrap column runs 343..737 in
   Hindi against 346..734 in English, so the taller lines are absorbed by the
   340px of slack a centred column already has. A rule here would have been
   decoration. testing/test_documentary_selector.py asserts the fit on this
   screen in Hindi, so if a longer chapter list ever does overflow it, it fails
   loudly rather than silently pushing "सूची पर लौटें" off the panel. */

/* [DEV-5] The wall status line that used to sit at the right end of the topbar
   is gone. It reported the state of a machine ("Wall display linked" /
   "Preview mode · plays on this screen"), which is not something a gallery
   wall says to a visitor, and it was the longest run of Hindi chrome on the
   home screen. The instruction now carries the only part of it that concerned
   anybody: where the film will appear. The topbar is one title and one line,
   so nothing there needs pinning any more. */

/* [DEV-6] The instruction is longer in Hindi than in English and is the only
   free-width element left in the topbar. It is allowed two lines rather than
   being clipped: it is the sentence the whole screen depends on. Cap the
   measure so a long line does not run under the Home pill on the right. */
.topbar .title .lede { max-width: 26em; }

/* [DEV-7] The language LABEL is manifest copy ("English", "हिंदी") and is
   printed on the now-playing badge, which is not otherwise bounded. A mistyped
   label in a hand-edited manifest grew it to 996px across the screen. */
.langbadge { max-width: 16em; overflow: hidden; white-space: nowrap;
             text-overflow: ellipsis; }

/* ==== HH LOGO STYLE, PROPAGATED FROM THE QUIZ (Vivek 16 Aug 21:52) =========
   The quiz's approved logo treatment, applied verbatim (see apps/quiz/app.css
   revisions 11-14 for the full reasoning):
   1. Attract screen: stacked lockup top right - the REAL standalone emblem
      (hh-emblem.png, two-tone, rendered directly, never a single-ink mask)
      over "Handloom Haat" in the credit's voice, upright, small caps.
   2. The framework's horizontal .saver-mark img is hidden; the lockup stands
      in its place.
   3. In-app screens: NO top-right HH mark at all; the framework's bottom-left
      .wm-hh watermark (untouched) is the only in-app HH presence.
   FRAMEWORK CANDIDATE: this block is now duplicated across all six apps and
   belongs in kiosk.css/weave-saver.js on the next framework pass. */
.saver-mark img { display: none; }
.brand-watermarks .wm-hh-top { display: none; }
.saver-hh-row {
  position: absolute; z-index: 4; pointer-events: none;
  right: 1.4em; top: 1.1em;
  display: flex; flex-direction: column; align-items: center; gap: .35em;
}
.saver-hh-sym {
  height: calc(max(18px, .46em) * 2.84);
  width:  calc(max(18px, .46em) * 2.84 * 1.0117);
  background: url(../../framework/assets/hh-emblem.png) center / contain no-repeat;
  filter: drop-shadow(0 1px 4px rgba(8,6,4,.98))
          drop-shadow(0 0 10px rgba(8,6,4,.9))
          drop-shadow(0 0 22px rgba(8,6,4,.7));
}
.saver-hh-word {
  font-family: var(--sans); font-weight: 400; font-style: normal;
  font-size: max(18px, .46em);
  letter-spacing: .06em; text-transform: capitalize;
  font-variant-caps: small-caps; font-variant: small-caps;
  color: var(--ink);
  text-shadow: 0 0 3px rgba(8,6,4,.98), 0 1px 5px rgba(8,6,4,.98),
               0 0 18px rgba(8,6,4,.92), 0 0 34px rgba(8,6,4,.75);
}

/* v2.2.1, 17 Aug, VIVEK'S ITEM 3: "logos OUT of the weave and motif areas
   entirely", read together with his item 4, the khadi border bands. The marks
   have MOVED rather than been deleted: framework/weave-saver.js now weaves a
   khadi border between weave sections carrying one institution's emblem
   repeated saree-border style, cycling per border. So the attract screen's
   top-right lockup is retired here, because the identity it carried is now IN
   the cloth where he asked for it, and leaving both would show the same marks
   twice on one screen.
   HIDDEN, NOT DELETED, and deliberately so: this block is Vivek-approved work
   from 16 Aug 21:52 and the rules below it (.saver-hh-sym/-word geometry) are
   the record of how that lockup was built. One line restores it if he wants it
   back after seeing the borders. Scope: this is the ONLY change made in these
   five directories, per Bob's 11:07 extension.
   NOT TOUCHED: the framework's bottom-left .wm-hh watermark, and the quiz's
   own bottom-right cluster, which is separately Vivek-approved. */
.saver-hh-row { display: none; }
