/* shark's fin · app.css · only what the kit does not do (build 4, cut 4).

   the look is some chords v0.1.1, linked, never forked: some-chords/wireframe.css
   loads before this file and the body carries class="wf". the tokens, the face
   (Archivo, self-hosted in fonts/), the mono, focus, the 150ms move, the
   placeholder and every wf- part are the kit's. this file holds the layouts the
   kit lacks, under their own names: where a box sits, how wide a column is,
   how a row lays out. no colour, size of type or state look is decided here that
   the kit already decides.

   the grammar, from the kit: two inks on one paper, hairlines, no fill, no
   radius, no shadow, no gradient, no colour. state is dotted against solid. */

:root {
  /* the page column, from the boards: 1280 wide, 56px side padding, 1168 of content */
  --pad: 56px;
  --col: 1280px;
}

html, body { height: 100%; }
/* the map is the window. a page from the menu scrolls inside itself. */
body { margin: 0; overflow: hidden; }

/* the three file fields live in the shell, out of sight; a button on the record page clicks them. */
#importfile, #lbfile, #malfile { position: absolute; width: 1px; height: 1px; opacity: 0; padding: 0; min-height: 0; }

/* a key letter inside a keys line: the letter in ink, the rest quiet. */
.wf-key b { font-weight: 600; color: var(--ink); }

/* --- a page over the map -------------------------------------------------- */
/* each page opens over the map and scrolls inside itself. esc goes back. */
.page {
  position: fixed; inset: 0; z-index: 50;
  background: var(--paper);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
}
/* the menu button floats at the top right over every page, so the page's own bar
   keeps its right end clear of it. */
.page .bar { padding-right: max(var(--pad), 124px); }
.bar, .view, .foot { width: 100%; max-width: var(--col); margin: 0 auto; }
.bar {
  display: flex; gap: var(--s5); align-items: center;
  padding: var(--s5) var(--pad) var(--s4);
  border-bottom: 1px solid var(--ink);
}
.bar .wf-name { margin: 0; flex: none; }
.bar .wf-h { flex: 1; margin: 0; }
.baractions { display: flex; gap: var(--s3); align-items: center; }

.view { flex: 1; padding: 0 var(--pad) 44px; }
.view:focus { outline: none; }
/* a section of a page opens under a rule. */
.view h3.wf-h { margin: var(--s6) 0 var(--s3); padding-top: var(--s3); border-top: 1px solid var(--ink); }
.view h2.wf-h { margin: 0 0 var(--s3); }

/* a row of actions. */
.go { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }
.rapidstart .go, .profile .go { padding-top: var(--s4); }

/* a plain list: one thing a row, a dotted rule between. */
.plain li {
  padding: var(--s2) 0; border-bottom: 1px dotted var(--ink);
  min-height: var(--hit); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
}

/* wikipedia · ebert · nyt. the dots come from css, so the markup stays a row of links. */
.reads { display: flex; align-items: center; flex-wrap: wrap; }
.reads a:not(:last-child)::after { content: '\00a0·\00a0'; display: inline-block; text-decoration: none; }

/* --- rapid fire ----------------------------------------------------------- */
.rapidstart, .summary, .card { padding-top: var(--s6); max-width: 1168px; }
.cardcount, .cardyear { font-size: 12px; color: var(--ink-light); }
/* the film data on one baseline beside the title, as the board draws it. */
.cardhead { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s4); margin-top: var(--s2); }
/* the card's display sizes are his call (ruling 35); the kit has none. */
.cardtitle { margin: 0; font-size: 28px; line-height: 1.2; font-weight: 600; }
.cardhook { margin: var(--s2) 0 0; font-size: 24px; line-height: 1.24; color: var(--ink-light); max-width: 30ch; }
.card .buffer { margin-top: var(--s5); }
.buffer {
  font-family: var(--mono); font-size: 28px; line-height: 1.2;
  border-bottom: 1px solid var(--ink);
  width: 120px; padding: 6px 0 4px; min-height: var(--hit);
}
.cardkeys { margin-top: var(--s4); }
.cardtouch { display: none; }
.touchscore { width: 120px; text-align: center; }

/* --- the record · the ledger ---------------------------------------------- */
.filters { display: flex; column-gap: var(--s5); row-gap: 0; flex-wrap: wrap; align-items: flex-end; padding-top: var(--s4); }
/* the kit has no select part, so the filter keeps its own (ruling 35): a label, then the field's line. */
.filter {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: var(--hit); font-size: 12px; color: var(--ink-light); cursor: pointer;
}
.filter select {
  appearance: none; -webkit-appearance: none;
  font-size: 13px; color: var(--ink); background: var(--paper);
  border: 0; border-bottom: 1px solid var(--ink-light); border-radius: 0;
  min-height: var(--hit); min-width: 72px; padding: 0 var(--s1); cursor: pointer;
}
.filter select:hover, .filter select:focus { border-bottom-color: var(--ink); }
/* loved only: a check drawn as the state pair, dotted off, solid on. his call (ruling 35). */
.filter.check { color: var(--ink); border-bottom: 1px dotted var(--ink); }
.filter.check:has(input:checked) { border-bottom: 1px solid var(--ink); font-weight: 600; }
.filter.check:has(input:focus-visible) { outline: 2px solid var(--ink); outline-offset: 3px; }
.filter.check input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }

.chartbox { padding: var(--s5) 0 0; }
.chartbox h3.wf-h { border-top: 0; padding-top: 0; margin-top: 0; }
/* the strip sits in the same scroll box the table uses. below 700 it keeps its
   own width and the box scrolls sideways, so the labels never scale down. */
.chart { width: 100%; min-width: 700px; height: auto; display: block; margin: var(--s4) 0 var(--s2); }
.chart .rule { stroke: var(--ink); stroke-width: 1; }
.chart .tick { stroke: var(--ink); stroke-width: 1; }
.chart .at { stroke: var(--ink); stroke-width: 1; stroke-dasharray: 2 3; }
.chart .lab { font: 12px var(--mono); fill: var(--ink-light); }
.chart .dot { fill: none; stroke: var(--ink); stroke-width: 1; }
/* love is the rising stroke, as on the map (ruling 33 A): one fact, one mark. */
.chart .up { stroke: var(--ink); stroke-width: 1.2; }
.lovedline { border-top: 1px solid var(--ink); padding-top: var(--s3); margin-top: var(--s4); }
.lovedline p { margin: 0; }

.tablewrap { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.wf-table { margin-top: var(--s4); }
.wf-table th[aria-sort] { cursor: pointer; white-space: nowrap; }
.wf-table th[aria-sort="descending"]::after { content: ' \2193'; color: var(--ink); }
.wf-table th[aria-sort="ascending"]::after { content: ' \2191'; color: var(--ink); }
.wf-table .note { color: var(--ink-light); max-width: 32ch; }
/* each ledger row opens with a quiet number. it is a count, not a sort key. */
.wf-table .rowno { width: 36px; padding-right: var(--s3); }
.wf-table .when, .wf-table .with { font-size: 12px; color: var(--ink-light); }
/* the score before a revision, beside the one he holds now. */
.wf-table .was { font-size: 11px; }

#ledgerbody { margin-top: var(--s5); border-top: 1px solid var(--ink); padding-top: var(--s3); }

/* --- the record · the profile --------------------------------------------- */
.profile { padding-top: var(--s5); max-width: 900px; }
.weights { display: flex; flex-direction: column; }
/* the groups read-back (build 3), wire marks: a card is a hairline box, a card
   crossed out is dotted, a name not kept is struck through. */
.gcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s4); }
.gcard { border: 1px solid var(--ink); padding: var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.gcard.off { border-style: dotted; }
.gcard .weight { grid-template-columns: minmax(0, 1fr) 48px; border-bottom: 0; }
.gcard .wslide { grid-column: 1 / -1; width: 100%; }
.gcompany { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); }
.gcompany .wf-in { width: 16ch; }
/* solo and with someone are always on: the kit's solid chip, never pressed. */
.wf-chip.fixed { border-style: solid; cursor: default; display: inline-flex; align-items: center; }
.gword { display: inline-flex; align-items: center; gap: var(--s1); }
.gnames li { display: flex; align-items: center; gap: var(--s1); }
.gnames li.crossed .gn { text-decoration: line-through; }
.weight {
  display: grid; grid-template-columns: minmax(0, 1fr) 200px 48px;
  gap: var(--s4); align-items: center;
  padding: 6px 0; min-height: var(--hit);
  border-bottom: 1px dotted var(--ink);
}
.wslide { width: 200px; accent-color: var(--ink); min-height: var(--hit); }
/* a weight is a number in its own column, flush right, in the mono. */
.wval { font-family: var(--mono); font-size: 12px; color: var(--ink-light); text-align: right; }
.confirm { margin-top: var(--s4); border-top: 1px dotted var(--ink); padding-top: var(--s3); }
/* the words the map did not know. a list to read, one word a row. */
.misses li { padding: 6px 0; border-bottom: 1px dotted var(--ink); }
.homein { width: 22ch; }
.recordpending { margin: var(--s4) 0 var(--s5); }

/* --- the page foot and the keys overlay ---------------------------------- */
.foot { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; min-height: 40px; padding: var(--s2) var(--pad); }
.foot .keys { margin-left: auto; }
/* the status line from app.js: a script hook, in ink, gone when it is empty. */
.status { color: var(--ink); margin-right: var(--s2); }
.status:empty { display: none; }
.help {
  position: fixed; right: 16px; bottom: 16px; width: 380px; z-index: 70;
  max-height: calc(100vh - 32px); overflow-y: auto;
  padding: var(--s4) var(--s5) var(--s5);
}
.help dl { display: grid; grid-template-columns: 148px 1fr; gap: var(--s2) var(--s4); margin: 0; }
.help dt { font-weight: 600; }
.help dd { margin: 0; color: var(--ink-light); }

/* --- the phone · 700px and under ------------------------------------------ */
@media (max-width: 700px) {
  :root { --pad: 20px; }
  .bar { padding: var(--s4) var(--pad) var(--s2); gap: var(--s3); flex-wrap: wrap; }
  /* the page's bar stays at the top while the page scrolls, so the menu box over
     it never covers a row (dry smoke). */
  .page .bar { padding-right: 80px; position: sticky; top: 0; z-index: 2; background: var(--paper); }
  .baractions { margin-left: auto; }
  .view { padding: 0 var(--pad) var(--s5); }
  .rapidstart, .summary, .card, .profile { padding-top: var(--s5); }
  .cardtitle { font-size: 24px; }
  .cardhook { font-size: 20px; }
  .cardkeys { display: none; }
  .cardtouch { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin-top: var(--s4); }
  .weight { grid-template-columns: minmax(0, 1fr) 48px; }
  .wslide { grid-column: 1 / -1; width: 100%; }
  .filters { gap: var(--s4); }
  .foot .keys { display: none; }
  /* a page's status line sits at the foot of the screen and takes no room when
     it is empty. the map's own lines live in its foot and its card. */
  .page .status {
    position: fixed; left: 0; right: 0; z-index: 51; margin: 0;
    bottom: 0; padding: var(--s2) var(--pad) calc(var(--s2) + env(safe-area-inset-bottom));
    background: var(--paper); border-top: 1px solid var(--ink-light);
  }
  /* 16px stops ios zooming the page when a field takes focus. */
  .touchscore, .filter select, .filter input.sq { font-size: 16px; }
  .help {
    left: 0; right: 0; width: auto; bottom: 0; max-height: 60vh;
    border-left: 0; border-right: 0; border-bottom: 0;
    padding: var(--s4) var(--pad);
  }
  .help dl { grid-template-columns: 120px 1fr; }
}

/* ---------------------------------------------------------------------------
   the map · the expanse. the canvas fills the window and boxes float over it:
   the bar, the menu, the card, the hover and the room. each is a kit box,
   opaque with a hairline (FL-22). this block places them.
   --------------------------------------------------------------------------- */

.expanse { position: fixed; inset: 0; background: var(--paper); overflow: hidden; }
.fcanvas {
  position: absolute; inset: 0; display: block; width: 100%; height: 100%;
  cursor: crosshair; touch-action: none;
}

/* the bar · one box for a title and for a night. its answer drops under it. */
.fbarbox {
  position: absolute; top: 16px; left: 16px; z-index: 10;
  width: min(520px, calc(100vw - 160px));
}
/* the bar's edge: the day's city file is old (FL-59), a save was refused (build 5). marks. */
.fbar-old { position: absolute; top: 0; right: var(--s3); line-height: 44px; font-size: 12px; pointer-events: none; display: flex; gap: var(--s2); }
.fdrop { max-height: min(460px, calc(100vh - 110px)); overflow-y: auto; }
.fdrop p { margin: var(--s2) 0 0; }
.fdrop .wf-list { margin-top: var(--s2); }
.freadback { padding-bottom: var(--s1); }
.fgates { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.fgates .wf-dim { margin: 0; }
/* a cinema pick whose show started after the deal: struck through, and marked past. */
.wf-row.past .wf-sub-line { text-decoration: line-through; }
.fpast { margin-left: var(--s2); font-size: 12px; }

/* the card · at the right, under the menu, never over the film it shows. */
.fcard {
  position: absolute; top: 72px; right: 16px; z-index: 10;
  width: 340px; max-height: calc(100vh - 112px); overflow-y: auto;
  padding: var(--s3);
}
.fcard-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s2); }
.fcard-head .wf-h { margin: 12px 0 var(--s1); }
#cardstatus { margin: var(--s2) 0 0; }
.fcard .wf-list { margin: 0 0 var(--s2); }
.fcard .wf-list li { display: flex; align-items: center; gap: var(--s1); min-height: var(--hit); flex-wrap: wrap; }
.fcard .wf-list .wf-dim { display: inline; margin: 0; }

/* the menu · top right. the app's name is the first word in it. */
.fmenuwrap { position: fixed; top: 16px; right: 16px; z-index: 60; }
/* the open menu draws its button's line in ink until the kit's hover step is ruled (ruling 40). */
.fmenubtn[aria-expanded="true"] { border-color: var(--ink); }
.fmenu {
  position: absolute; top: 52px; right: 0; width: 220px;
  display: flex; flex-direction: column; padding: var(--s2);
}
.fmenu .wf-name { margin: var(--s1) var(--s2) var(--s2); }
.fmenu-item { display: flex; justify-content: space-between; padding: 0 var(--s2); }
/* the underline is the action's word; its key letter beside it stays a quiet key. */
.fmenu-item { text-decoration: none; }
.fmenu-item > span:first-child { text-decoration: underline; text-underline-offset: 2px; }
.fmenu-item:hover > span:first-child { text-decoration-thickness: 2px; }

/* the foot · one quiet line across the window on its own ground, so no node or
   label crowds it (FL-25): the stamp, the count, the legend, credits. */
.ffoot { position: absolute; left: 0; right: 0; bottom: 0; z-index: 5; display: flex; align-items: center; flex-wrap: wrap; column-gap: 0; }
.ffoot .wf-act { min-height: 0; min-width: 0; margin-left: var(--s2); font-size: 11px; }
.ffoot .wf-act::before { content: '·\00a0'; display: inline-block; text-decoration: none; }

.fhover { position: absolute; z-index: 12; }

/* the pieces inside the card that the kit has no part for. */
.wire-links { display: flex; flex-wrap: wrap; gap: var(--s3); margin: 0 0 var(--s2); }
.wire-acts { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s2); }
.wire-reason { display: flex; gap: var(--s2); align-items: center; margin: 0 0 var(--s2); }
/* the FL-5 row. the score is a short field, the note takes the width of the card. */
.wire-scorerow { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin: 0 0 var(--s2); }
.wire-scorerow .wire-scorein { width: 76px; }
.wire-scorerow .wire-notein { width: 100%; }
.wire-scorerow .wire-sel { width: auto; flex: 1 1 120px; }
/* the runtime, last on the card, folded behind its owed mark. */
.wire-fold { margin-top: var(--s2); }
.wire-runtime { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-top: var(--s2); }
.wire-runtime .wire-runtimein { width: 172px; }

/* the phone · the bar across the top, the menu beside it, the card a sheet from
   the bottom to half the screen. the map stays live behind it. */
@media (max-width: 700px) {
  .fbarbox { top: 8px; left: 8px; right: 76px; width: auto; }
  .fmenuwrap { top: 8px; right: 8px; }
  .fmenubtn .fkey { display: none; }
  /* credits in the foot is a target like any other on a phone: 44px (dry smoke). */
  .ffoot .wf-act { min-height: var(--hit); min-width: var(--hit); }
  .fdrop { max-height: 40vh; }
  .expanse.card-open .fdrop { display: none; }
  .fcard {
    top: auto; right: 0; left: 0; bottom: 0;
    width: auto; height: 50vh; max-height: 50vh;
    border-left: 0; border-right: 0; border-bottom: 0;
    padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom));
  }
}

/* --- screens · the screen register (FL-46) ------------------------------- */
/* the ledger's ruled table. a cell that has no source reads owed; a mark sits
   small after the value and never takes the value's place. */
.screens td.scin { font-weight: 600; max-width: 30ch; }
.screens td.saudi, .screens td.sval { white-space: nowrap; }
.screens i { font-style: italic; color: var(--ink-light); }
.mk { font-size: 10px; font-weight: 600; color: var(--ink); margin-left: 2px; }
span.mk { font-size: 13px; margin-left: 0; }
.screens tr.srow { cursor: pointer; }
.screens tr.srow[aria-expanded="true"] td { border-bottom: 1px solid var(--ink); }
.screens tr.srcopen td { padding: var(--s3) 0 var(--s4); height: auto; border-bottom: 1px solid var(--ink); }
.srcgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: var(--s3) var(--s5); }
.srch { margin: 0 0 var(--s2); font-weight: 600; }
.srcrow {
  display: grid; grid-template-columns: 76px minmax(90px, 1fr) minmax(90px, 1fr) auto auto;
  gap: var(--s3); align-items: baseline; min-height: 28px;
  border-bottom: 1px dotted var(--ink);
}
.srck { color: var(--ink-light); font-size: 12px; }
.srcv, .srclink { color: var(--ink); overflow-wrap: anywhere; }
.srcd { color: var(--ink-light); font-size: 12px; white-space: nowrap; }
.legend { display: flex; flex-wrap: wrap; gap: var(--s4); margin: var(--s2) 0 0; color: var(--ink-light); }
.legend .mk { margin: 0 2px 0 0; }
.filter input.sq { width: 16ch; }
#screensbody { margin-top: var(--s4); border-top: 1px solid var(--ink); padding-top: var(--s3); }
/* the rows scroll inside their own box, and the head row stays. the page does not scroll. */
#screensbody .tablewrap { max-height: calc(100vh - 330px); overflow: auto; }
.screens thead th { position: sticky; top: 0; background: var(--paper); z-index: 1; }
.screens { margin-top: 0; }
@media (max-width: 700px) {
  .srcrow { grid-template-columns: 64px 1fr; }
  .srcrow .srcd, .srcrow .srclink { grid-column: 2; }
  .srcrow > :empty { display: none; }
}

/* --- the city on the map (FL-48) ------------------------------------------ */
/* a show on a city film's card is a row and a button. the one chosen for watch it
   is told apart by weight and a rule, never a colour (ruling 34 A). */
.fshows li { margin: 0; }
.fshow { display: block; width: 100%; text-align: left; padding: 6px 0; font-size: 12px; line-height: 1.45; }
.fshow[aria-pressed="true"] { font-weight: 600; border-left: 2px solid currentColor; padding-left: 6px; }

/* --- the fold (FL-51) ------------------------------------------------------ */
/* the room is a press: its name under a cinema pick and before each show on a
   city film's card. one underline, the kit's action word, never a colour. */
.froom { font-size: 12px; }
.wf-list li > .froom { margin: -4px 0 2px; }
.fshows .froom { flex: none; }
.fshows .fshow { flex: 1 1 160px; width: auto; }
/* route (FL-61): a link, the kit's underline, 44px tall like the room press. */
.froute { font-size: 12px; }
.wf-list li > .froute { margin: -4px 0 2px var(--s2); }
.fshows .froute { flex: none; }
/* the crowd on a show (FL-59): · open, ◐ filling, ● full. a mark in a fixed box,
   so a column of them lines up; never a colour. leave by sits beside it on a pick. */
.fcrowd { display: inline-block; min-width: 1.2em; text-align: center; }
.wf-list li > .fway { font-size: 12px; margin-left: var(--s2); }
/* the room's register row, in a box over the map. the camera, the picks and the
   card stay where they were under it. */
.froombox {
  position: absolute; left: 16px; right: 16px; bottom: 40px; z-index: 20;
  max-height: min(70vh, 640px); overflow: auto; padding: var(--s3);
}
.froombox .wf-table { margin-top: var(--s2); }
.froombox .legend { margin-top: var(--s2); }
.froombox .wf-dim { font-size: 12px; margin: var(--s2) 0 0; }
@media (max-width: 700px) {
  .froombox { left: 0; right: 0; bottom: 0; max-height: 70vh; border-left: 0; border-right: 0; border-bottom: 0; }
}
