﻿/* The go binder.
 *
 * Printing is a first-class output, not a courtesy: on the day this product matters there may be no
 * power, no internet and no charged phone, and the sheet in the binder by the door is the roster.
 * So this is a design of its own rather than a screenshot of the screen — the whole pine-and-paper
 * surface is dropped for ink on paper, because color costs toner and contrast costs nothing.
 *
 * Linked with media="print" so it never touches the screen, and loaded on every page: any page a
 * coordinator can reach, they can print.
 */

@page {
    size: letter;

    /* Narrow on purpose. This sheet is not a document somebody reads in a chair — it is a working
       page carried door to door, and every tenth of an inch at the edge is width the map does not
       have. Well inside the unprintable margin of any consumer laser or inkjet, which is about a
       quarter inch. */
    margin: 0.3in;
}

@media print {

    /* Sizes go to points here. A sheet read by flashlight at arm's length needs 12pt body, which is
       the floor everywhere below. */
    html, body {
        font-size: 12pt;
        line-height: 1.4;
        color: #000;
        background: #fff;
    }

    body {
        font-family: 'Libre Franklin', system-ui, sans-serif;
    }

    /* Everything that exists to navigate a screen. None of it means anything on paper, and all of it
       costs a line somebody could have written on. */
    .br-masthead,
    .br-offline,
    /* The context bar wraps its nav in a div, so hiding `nav` alone would leave an empty white band
       with a rule under it at the top of every printed sheet. */
    .br-trail,
    /* Likewise the neighbor's-eye strip, which would otherwise print as a solid amber block — and
       what a coordinator carries is the same sheet either way. */
    .br-preview,
    .br-tabs,
    .br-skip,
    .btn,
    form,
    nav,
    .br-footer,
    .no-print {
        display: none !important;
    }

    /* Sheets stop being sheets: no fill, no border, no radius. */
    .br-sheet,
    .br-panel-pine,
    .alert,
    .br-list,
    .card {
        color: #000 !important;
        background: #fff !important;
        border: none !important;
        border-radius: 0 !important;
    }

    .br-sheet__body,
    .br-list a {
        padding: 0 !important;
    }

    /* A drawing that says "nothing here yet" costs a third of a page and tells a reader nothing they
       cannot see for themselves. */
    .br-mark-empty {
        display: none !important;
    }

    /* The map survives printing, but the panel of names behind each pin does not: it only exists
       because a screen can hide things until they are asked for, and paper cannot. The names belong
       on the roster sheet, which has room to set them properly. */
    .br-map__card {
        display: none !important;
    }

    /* The frame is a positioning context for the pins and must stay one on paper, or every pin
       collapses to the top-left corner of the page. */
    .br-map__frame {
        position: relative !important;
    }

    /* The pannable map does not print — it is a live canvas of tiles that may not even have loaded,
       and panning is not a thing paper does. The static picture underneath comes back instead, which
       is what it was always for. */
    .br-map__live {
        display: none !important;
    }

    .br-map--live .br-map__frame--replaced {
        display: block !important;
    }

    /* The button that asks for tiles is a thing you press. Paper has nothing to press. */
    .br-map__tiles {
        display: none !important;
    }

    /* On screen the map and the list share a row and each one scrolls. On paper they stack, and
       NOTHING SCROLLS: a rail that keeps its scrollbar prints five households and silently loses the
       other eleven, which is the one failure a go-binder sheet cannot have.

       This is also what makes the printed sheet worth having. The map shows where everybody is, the
       list under it gives every house number, who lives there, and — if the page was printed under a
       filter — which of them have the thing you went looking for. */
    .br-map {
        display: block !important;
        max-width: none !important;
    }

    .br-map__sheet {
        max-height: none !important;
        overflow: visible !important;
        border-left: 0 !important;
        border-top: 1pt solid #767676 !important;
    }

    .br-map__rail,
    .br-map__legend {
        max-height: none !important;
        overflow: visible !important;
    }

    /* Rows are read, not tapped, so they lose the 44px touch floor and the page gets more of them. */
    .br-map__rail-row {
        min-height: 0 !important;
        padding: 3pt 6pt !important;
        break-inside: avoid;
    }

    /* The list on paper is a list of names, not a list of muted names: whoever is holding this sheet
       is standing in the street, and ink that says "less important" costs them a household. */
    .br-map__rail-row--dim,
    .br-map__rail-names {
        color: #000 !important;
    }

    /* The grab bar and the disclosure arrow are both promises about tapping. */
    .br-map__handle,
    .br-map__filter-chevron {
        display: none !important;
    }

    /* The rem-based tokens inherit from the 12pt root, so body-scale text printed at 11.25pt and
       helper text at 9.75pt — under the floor this file opens by declaring. Restated in points, at
       the sizes a sheet read by flashlight actually needs. */
    p, li, td, th, div, span, a {
        font-size: 12pt;
    }

    .br-note,
    .form-text {
        font-size: 12pt;
    }

    h1 { font-size: 24pt; }
    h2 { font-size: 15pt; }
    h3 { font-size: 13pt; }

    /* The printed masthead is the sheet's own header, not the app's. */
    .br-binder-head {
        display: block !important;
        padding-bottom: 8pt;
        border-bottom: 2.5pt solid #000;
    }

    .br-binder-head h1 {
        margin: 0;
        font-size: 24pt;
        letter-spacing: -0.02em;
    }

    .br-binder-head__meta {
        font-size: 10pt;
    }

    h1, h2, h3 {
        color: #000;
        break-after: avoid;
        page-break-after: avoid;
    }

    /* A household must never be split across a page boundary — half a row is worse than none, since
       the half that carried the medical note might be the half that got left behind. */
    table {
        width: 100%;
        border-collapse: collapse;
    }

    thead {
        display: table-header-group; /* the head repeats on every page */
    }

    tr, .br-household {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    .table > thead th {
        padding: 4pt 6pt;
        font-size: 9pt;
        color: #000;
        border-bottom: 1.5pt solid #000;
    }

    .table > tbody td {
        padding: 7pt 6pt;
        font-size: 12pt;
        border-bottom: 0.5pt solid #000;
    }

    /* Chips and stamps become plain words: a tinted pill prints as a grey smear. */
    .br-chip,
    .br-stamp {
        padding: 0;
        margin: 0 0.4em 0 0;
        font-size: 12pt;
        font-weight: 400;
        color: #000 !important;
        background: none !important;
        border: none !important;
        letter-spacing: 0;
    }

    .br-stamp {
        font-weight: 700;
        text-transform: uppercase;
    }

    .br-chip--private {
        font-weight: 700;
    }

    /* A tick box for the welfare check. The sheet is meant to be written on. */
    .br-tickbox {
        display: inline-block;
        width: 11pt;
        height: 11pt;
        border: 1pt solid #000;
    }

    a {
        color: #000;
        text-decoration: none;
    }

    /* Anything that exists only on paper. The matching `display: none` lives in site.css: a rule
       inside a stylesheet linked media="print" only applies while printing, which is exactly when
       this must not hide. */
    .print-only {
        display: block !important;
    }

    /* THE CONTAINER IS A SCREEN IDEA AND HAS NO BUSINESS ON PAPER.
       Bootstrap's .container clamps to a max-width chosen by breakpoint, and the breakpoint it picks
       is decided by the PRINTABLE width — 7.9in of a letter page is 758px, which lands in the
       576-767px tier and clamps everything to 540px. That stranded 121px of blank paper down each
       edge and squeezed the map to two and a half inches, and it looks exactly like a page margin,
       which is the wrong place to go hunting for it.

       Paper already has margins: @page sets them. */
    .container {
        max-width: none !important;
        width: auto !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    /* The block and the instructions, side by side. A full-width map is two thirds of the first
       page and puts every household after it — which is exactly backwards for a sheet somebody
       carries door to door. Kept together on one page: the map is the orientation for the steps
       beside it. */
    /* Stacked, not side by side. Beside the instructions the map was under half the width and there
       was blank paper below the brief, because our map is a square picture of the real world and the
       mockup's was a landscape strip. Full width is the bigger map and the tidier page.

       NOT break-inside: avoid. The map is nearly as tall as the printable area, so a rule keeping it
       and the instructions together would have nowhere to put them. They break apart if they must;
       the brief keeps its own avoid, because half a list of steps is worse than a page turn. */
    .br-binder-top {
        display: block !important;
        margin-bottom: 8pt !important;
    }

    .br-binder-top .br-map--binder {
        width: 100% !important;
        margin: 0 0 8pt 0 !important;
    }

    .br-binder-top .br-binder-brief {
        margin: 0 !important;
    }

    /* ---- What the map draws on paper -----------------------------------------------------------
       The picture behind these is an image and prints whatever the printer does. Everything WE draw
       over it has to survive a printer with backgrounds switched off, which is most of them by
       default — so the rule here is simple: nothing that matters may be carried by a background or
       a shadow. Borders and strokes print. Fills and box-shadows are a coin toss. */

    /* A household. On screen it is an emerald dot with a pale ring !important; both of those are a background
       and a shadow, so on paper it arrived as a white circle with nothing in it — invisible on a
       pale roof and unreadable on any. A drawn ring survives anything.

       EVERY DECLARATION BELOW IS !important, and not for emphasis: map.css is linked after this file
       and shares its specificity, so without it the screen's emerald simply wins. That is why almost
       every rule in this stylesheet already carries one. */
    .br-map__marker {
        width: 11pt !important;
        height: 11pt !important;
        background: #FFFFFF !important;
        border: 1.25pt solid #000000 !important;
        box-shadow: none !important;
        box-sizing: border-box !important;
    }

    /* Yours. An outline rather than a second box-shadow, because outlines print and shadows do not —
       and a shape difference rather than a weight difference, so it is still legible when the ring
       beside it is the same ink. */
    .br-map__pin--own .br-map__marker,
    .br-map__marker-icon--own .br-map__marker {
        box-shadow: none !important;
        outline: 1pt solid #000000 !important;
        outline-offset: 1.25pt !important;
    }

    /* A shared place. Its border already printed; its glyph did not, because the sprite was only on
       the map page — that is fixed in the markup. This makes the ink black rather than the mid-grey
       that emerald and amber both reduce to. */
    .br-map__place-mark,
    .br-map__place-icon .br-map__place-mark {
        width: 20pt !important;
        height: 20pt !important;
        color: #000000 !important;
        background: #FFFFFF !important;
        border: 1.25pt solid #000000 !important;
    }

    .br-map__place-mark svg {
        width: 11pt !important;
        height: 11pt !important;
    }

    /* Coordinator-only places are amber on screen, and amber is a mid-grey on paper — the same
       mid-grey emerald reduces to, which would make the two say nothing. Dashed carries it instead,
       which is the grammar this system already uses for a PENDING stamp. */
    .br-map__place--private .br-map__place-mark,
    .br-map__place-mark--private {
        border-style: dashed !important;
    }

    /* ---- The roster sheet ---------------------------------------------------------------------
       Ink on paper at point sizes. The screen's card becomes a ruled row, because what a sheet in a
       binder needs is density and a straight edge to run a finger down. */

    .br-roster {
        border: none;
        border-radius: 0;
        gap: 0;
    }

    /* ONE BOX PER HOUSEHOLD. A hairline between them is enough on a screen you scroll; on a sheet
       somebody runs a finger down in the dark, sixteen homes separated by a rule read as one column
       of text, and the eye has to count line breaks to find where one home ends. A box is a boundary
       nobody has to look for, and it is pure line art, which costs a printer nothing. */
    .br-roster__row {
        padding: 4pt 5pt;
        margin-bottom: 3pt;
        border: 0.75pt solid #000;
        border-radius: 0;
        /* Half a household is worse than none when the half left behind is the one with the
           medical note. */
        break-inside: avoid;
        page-break-inside: avoid;
        display: grid;
        grid-template-columns: 16pt 1fr;
        gap: 0 6pt;
        background: none;
    }

    /* Yours, on paper: a heavier box rather than a tint, because a background is the one thing that
       reliably does not print. */
    .br-roster__row--own {
        border-width: 1.5pt;
    }

    /* The tick column, and the reason this prints at all: the sheet is meant to be written on as
       somebody walks the block. */
    .br-roster__row > .br-tickbox {
        grid-row: 1 / span 3;
        align-self: start;
        margin-top: 2pt;
    }

    .br-roster__who,
    .br-roster__facts,
    .br-roster__private {
        grid-column: 2;
    }

    .br-roster__address {
        font-size: 11pt;
    }

    .br-roster__phone {
        min-height: 0;
        margin-right: 6pt;
    }

    /* The dashed rule that separates the private half on screen stays, because on paper it is what
       tells a coordinator which half of this sheet must not be photocopied for the block. */
    .br-roster__private {
        margin-top: 4pt;
        padding-top: 3pt;
        border-top: 0.5pt dashed #000;
    }

    .br-roster__facts {
        grid-template-columns: 54pt 1fr;
        gap: 1pt 6pt;
        margin-top: 3pt;
    }

    .br-roster__facts dt {
        font-size: 7pt;
    }

    .br-roster__count,
    .br-roster__people--none {
        color: #000;
    }

    /* The instructions and the join code. Kept together on one page: a torn-off half of "check your
       own household first" is worse than nothing. */
    .br-binder-brief {
        break-inside: avoid;
        page-break-inside: avoid;
        border: 0.5pt solid #000;
        padding: 6pt 8pt;
        margin-bottom: 8pt;
    }

    .br-binder-brief h2 {
        font-size: 9pt;
        margin-bottom: 3pt;
    }

    .br-binder-brief ol {
        margin: 0 0 3pt;
        padding-left: 12pt;
    }

    /* The join code and its square, side by side. Not floated or wrapped: the square has a fixed
       size and the words take what is left, because a QR that reflows is a QR that eventually
       prints at a size nothing can read. */
    .br-binder-join {
        display: flex;
        align-items: center;
        gap: 10pt;
        margin-top: 5pt;
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* 90pt is 1.25in, and the size is the whole decision. A version-4 code inside it puts each
       module at about 0.9mm, which a phone camera resolves by torchlight; the error-correction
       level was kept at Medium rather than spending that millimetre on a denser grid — see
       JoinCodeQr. Fixed in points because paper is fixed: a percentage would make the square depend
       on how wide the brief happened to lay out. */
    .br-binder-qr {
        flex: 0 0 auto;
        width: 90pt;
        height: 90pt;
        display: block;
    }

    /* No size override here, deliberately. Eight points fitted the sentence beside the square in one
       fewer line and put it under the 12pt floor this file opens by declaring — which is the size a
       sheet has to be to be read by flashlight, and this is the line somebody reads by flashlight.
       The square gives the words less room; it does not buy a smaller typeface. */
    .br-binder-join__note p {
        margin: 0;
    }

    /* The half of this that gets typed, set like something to be typed: large, spaced, and on its
       own line so the eye finds it without reading the sentence under it first. */
    .br-binder-join__code {
        display: block;
        font-size: 15pt;
        letter-spacing: 0.06em;
        margin-bottom: 2pt;
    }

    .br-roster-tally,
    .br-roster-meet {
        margin-bottom: 4pt;
    }

    /* A disclosure prints open, always. On screen a closed summary is a fair trade for a shorter
       form; on paper it is a field that silently does not exist, and the one it hides most often is
       a child's school. Paper has no affordance for opening anything, so the page has to arrive
       open. `content-visibility` is what actually decides this in Chromium — `open` alone is
       ignored by the print renderer. */
    details > summary {
        list-style: none;
    }

    details:not([open]) > *:not(summary) {
        display: revert !important;
        content-visibility: visible !important;
    }

    /* The two-step confirmation on a destructive action is screen-only. On paper it is a heading
       over a button nobody can press. */
    .br-summary,
    .br-summary + p,
    .br-summary ~ form {
        display: none !important;
    }

    /* ---- The OK card ----------------------------------------------------------------------------
       The only thing BlockReady does on the day, and it is a piece of paper in a window. Two to a
       sheet: the word has to be recognisable from the pavement through glass, and four to a page
       halves it to save paper nobody was short of.

       @page leaves 10.4in of printable height, so two cards at 4.9in with a gap between them fill a
       sheet without spilling a third onto the next one.

       EVERY DECLARATION IS !important, for the same reason the map markers' are: signs.css is linked
       from the page's Styles section, which the layout renders AFTER this file, so at equal
       specificity the screen's rule simply wins. Without it the card printed at its 40rem screen
       width — 640px of an 816px page — with its screen corner radius still on. */
    .br-okcard {
        height: 4.9in !important;
        width: 100% !important;
        max-width: none !important;
        aspect-ratio: auto !important;
        margin: 0 0 0.2in !important;
        padding: 0.2in !important;
        background: none !important;
        border: 3pt solid #000 !important;
        border-radius: 0 !important;
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* Roughly three inches of letterform, which is what "readable at thirty feet without stopping"
       costs. Everything else on the card exists to not compete with it. */
    .br-okcard__word {
        font-size: 190pt !important;
        line-height: 0.85;
        color: #000 !important;
    }

    .br-okcard__says {
        font-size: 16pt !important;
        color: #000 !important;
    }

    .br-okcard__whose {
        font-size: 11pt !important;
        color: #000 !important;
    }
}
