/* Volunteer interface. Built for a phone, a weak network and an unpractised user.
 *
 * The decisions worth knowing about:
 *   * 18px base text and 1.65 line-height. Many volunteers are over sixty.
 *   * Every target is at least 52px tall — a thumb, not a mouse pointer.
 *   * The main action sits at the bottom of the screen, where the thumb rests.
 *   * Status is a sentence plus a shape, never a colour on its own.
 *   * No framework, no web fonts, one stylesheet. It has to open on 3G.
 *   * Dark mode follows the phone, because the phone is usually already set.
 */

:root {
  color-scheme: light dark;

  --ink: #16202b;
  --ink-soft: #4a5a6a;
  --page: #f4f6f8;
  --card: #ffffff;
  --line: #d7dee5;

  --brand: #0b5d5a;
  --brand-ink: #ffffff;
  --brand-soft: #e3f0ef;

  --good: #136f3b;
  --good-soft: #e4f3ea;
  --wait: #8a5a00;
  --wait-soft: #fbf0d9;
  --stop: #9b2226;
  --stop-soft: #fbe9e9;

  --radius: 14px;
  --gap: 16px;
  --tap: 52px;
  /* The floor for anything a thumb has to find: 44px is the smallest target a person
     hits reliably, and it is what WCAG 2.5.5 asks for. `--tap` stays larger for the
     things a person reaches for on purpose. */
  --tap-small: 44px;
  /* The floor for a target that is a figure rather than a control: WCAG 2.5.8's
     minimum. Separate from `--tap-small` on purpose — see `.spread > span > a`. */
  --tap-tiny: 24px;
  --shadow: 0 1px 2px rgba(22, 32, 43, 0.08), 0 4px 14px rgba(22, 32, 43, 0.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e9eef3;
    --ink-soft: #a8b6c4;
    --page: #11171d;
    --card: #1a222b;
    --line: #2e3a46;
    --brand: #4fd1c5;
    --brand-ink: #06232b;
    --brand-soft: #16302f;
    --good: #6ddba0;
    --good-soft: #163026;
    --wait: #f0c674;
    --wait-soft: #332a16;
    --stop: #f09292;
    --stop-soft: #331b1b;
    --shadow: none;
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0;
  /* A column, so a page with little on it still puts the bar at the bottom of the
     screen rather than halfway up it. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--page);
  color: var(--ink);
  /* 1.125rem, not 18px. The two are the same thing on a browser left alone — the root
     is 16px — but `18px` is a size the person cannot change. Everything that inherits
     from here does: every button label, every form field, every table cell. Measured
     at 250% text: headings and leads grew because they are sized in rem, and the
     buttons stayed at 18px, so the screen a volunteer enlarged was half enlarged.
     WCAG 1.4.4 asks that text can be resized to 200% without loss of content or
     function, and a label that refuses to grow is the loss. */
  font: 1.125rem/1.65 system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  /* Hebrew and Arabic both read right to left; `dir` is set on <html>. */
  /* A word wider than the column breaks instead of pushing the whole page sideways.
     It happens with a long Arabic name — عبد الرحمن أبو العسل الهواشلة — with a place
     name a council types in full, and at 250% text with an ordinary Hebrew word:
     "שממשיכים" at that size is wider than a 320px screen's column. `break-word` only
     acts when the word alone does not fit, so ordinary wrapping is untouched. */
  overflow-wrap: break-word;
}

/* Anything Latin or numeric inside right-to-left prose keeps its own order. */
.ltr { direction: ltr; unicode-bidi: isolate; }
/* A time range is one word. Broken over two lines it reads as a different time. */
.nowrap { white-space: nowrap; }

.skip {
  position: absolute;
  inset-inline-start: -9999px;
}
.skip:focus {
  inset-inline-start: var(--gap);
  top: var(--gap);
  z-index: 10;
  background: var(--card);
  /* The first thing a keyboard reaches on every screen, so it is a full target. */
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-small);
  padding: 0 16px;
  border-radius: var(--radius);
}

/* ------------------------------------------------------------------ layout */
.shell {
  max-width: 560px;
  margin: 0 auto;
  /* No room is reserved for the bottom bar any longer. It used to be 6rem, a guess at
     how tall a bar outside the flow would be, and a guess is what it had to be. The
     bar is sticky now and keeps its own space, so what is left here is the ordinary
     bottom margin of a page. */
  flex: 1 0 auto;
  width: 100%;
  box-sizing: border-box;
  padding: 0 var(--gap) calc(var(--gap) + env(safe-area-inset-bottom));
}

header.bar {
  background: var(--brand);
  color: var(--brand-ink);
  padding: 14px var(--gap);
}
header.bar .inner {
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* At 250% text the council's name and the two tools together are 372px wide on a
     320px screen, and the tools ran off the edge — on every screen, because this bar
     is on every screen. Wrapping is the right answer rather than shrinking the text:
     the person who set it that large did so because they need it. */
  flex-wrap: wrap;
}
/* The two controls that are on every screen were 42x25 and 35x25 — a quarter of a
   thumb. They are the language switch and the way out, so missing them is either
   reading the wrong language or staying signed in on a shared phone. The bar's own
   padding is reduced by the same amount the links grow, so the bar does not get
   taller and nothing below it moves. */
header.bar a,
header.bar .linkish {
  color: var(--brand-ink);
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-small);
  padding: 0 6px;
  margin: calc((var(--tap-small) - 1.5rem) / -2) 0;
}
/* The way out became a form when it stopped being a GET. It has to keep the size it
   had — it is one of the two controls on every screen, and the comment above is about
   how hard it was to hit. So the button inherits the bar's own type and underline
   rather than a browser's button chrome, and the form itself takes no space. */
header.bar .bar-out { display: inline-flex; margin: 0; }
header.bar .linkish {
  background: none;
  border: 0;
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
header.bar .linkish:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
/* The mark in the bar. Sized in **px and not rem** on purpose: at 250% text the bar
   already measures 372px of a 390px screen (see `.inner` above), and a logo that grew
   with the text would be the thing that pushed the language switch off the edge. It
   is decorative — the council's name is beside it — so it is the first thing to go
   when the bar runs out of room. */
.bar-logo {
  height: 28px;
  width: auto;
  flex: none;
  display: block;
}
@media (max-width: 360px) {
  .bar-logo { display: none; }
}
/* The council's plate in the bar, sized like the mark beside it and dropped at the
   same width, for the same reason: at 250% text the bar is already 372px of a 390px
   screen, and two logos plus a name plus two tools do not fit. */
.bar-plate { padding: 3px 6px; border-radius: 8px; flex: none; }
/* `header.bar` in front, and not `.bar-plate img` alone. The generic
   `.logo-plate img` below is written later in this file and carries the same
   specificity, so it won — and the council's crest came out 56px tall in a bar
   that is 28, pushing the bar onto two rows. Measured, in a screenshot. Winning on
   specificity rather than on source order is what stops that returning the next
   time either rule moves.

   A width cap as well as a height one: an image that fails to load has no intrinsic
   size, and without it the plate stretched across the whole bar with a broken-image
   icon in it — which is what the first run of this looked like on a public page. */
header.bar .logo-plate img { max-height: 22px; max-width: 70px; }
@media (max-width: 360px) {
  .bar-plate { display: none; }
}
.bar-name { font-weight: 700; font-size: 1.05rem; }

/* The two logos together, where the product says whose project this is.

   `logo-plate` is white in **both** themes on purpose. Elaaf's own mark is a single
   colour and v0.37.0 gives it one variant per surface; a council's logo is whatever
   colours its designer chose and cannot be recoloured, so the only honest thing is to
   give it the background its designer assumed. The plate is what makes that true on a
   dark page and on a teal bar alike. */
.logo-plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  border-radius: 10px;
  padding: 6px 10px;
}
.logo-plate img { display: block; max-height: 56px; width: auto; }

.joint-lockup { margin: 8px 0 20px; }
.joint-logos {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Wraps rather than shrinks: at 250% text on a narrow screen two logos side by side
     do not fit, and a logo scaled down to fit is a logo nobody recognises. */
  flex-wrap: wrap;
  gap: 14px;
}
.joint-divider {
  width: 1px;
  align-self: stretch;
  min-height: 34px;
  background: var(--line);
}
.joint-words {
  margin: 10px 0 0;
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
.joint-logos .lockup { margin: 0; max-width: 220px; max-height: 76px; }

/* The lockup on a screen somebody meets before they are signed in. Capped by width
   **and** by height: it is 2.91:1, so a width cap alone would make it 190px tall on a
   wide screen and push the form below the fold on the one screen where the form is
   the point. `height: auto` with both caps keeps the aspect and lets the smaller cap
   win. */
.lockup {
  display: block;
  width: 100%;
  max-width: 320px;
  max-height: 110px;
  height: auto;
  object-fit: contain;
  object-position: center;
  margin: 8px auto 20px;
}
/* `margin-inline-start: auto` and not `space-between` on the parent: the bar has
   three things in it now and space-between would put the council's name in the
   middle, away from the mark it belongs to. This eats the free space instead, so the
   mark and the name stay together at the start and the tools stay at the end — and
   `flex-wrap` above still does what it did at 250% text. */
.bar-tools { display: flex; align-items: center; gap: 8px; font-size: 0.95rem;
             margin-inline-start: auto; }

h1 { font-size: 1.6rem; line-height: 1.3; margin: 26px 0 10px; }
h2 { font-size: 1.2rem; margin: 28px 0 10px; }
p { margin: 0 0 14px; }
.lead { color: var(--ink-soft); font-size: 1.05rem; }
.quiet { color: var(--ink-soft); font-size: 0.95rem; }

a { color: var(--brand); text-decoration-thickness: 2px; text-underline-offset: 3px; }
/* A link that is the whole of its paragraph or its cell is an action, not prose — and
   it was 19 to 21 pixels tall, including "remove" next to somebody's name on the roles
   screen, which revokes their authority. A link inside a sentence is left alone: a
   person reading prose is not aiming at it with a thumb. */
p > a:only-child,
.spread > span > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-small);
  /* And a floor on the width, because a figure link can be one character wide:
     measured at **7px** on `/manage/dashboard`, where the number of things waiting is
     the link. `--tap-small` is not used for the width — a 44px box around a single
     digit is what pushes a 320px screen into sideways scrolling, and that is a worse
     failure than a small target. 24px is the minimum WCAG 2.5.8 asks for. */
  min-width: var(--tap-tiny);
}

/* ------------------------------------------------------------------- cards */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin: 0 0 14px;
}
.card.feature { border-inline-start: 6px solid var(--brand); }
/* A card's title is an `h2` because it is the first level under the page's `h1`:
   twenty-five screens went straight from `h1` to `h3`, so anyone moving by heading —
   which is how a screen-reader user reads a list of cards — met a level that was not
   there and had no way to tell whether they had missed a section. Both selectors are
   here so the two render identically and a card inside a section can still be an
   `h3`. */
.card h2, .card h3 { margin: 0 0 8px; font-size: 1.15rem; line-height: 1.35; font-weight: 700; }
/* A label beside its value, until the two no longer fit side by side — then one above
   the other. `min-width: 4.5em` is 72px at normal text and 180px at 250%, so a row
   holding a label and a status pill was 409px wide on a 320px screen and pushed the
   whole page sideways. Stacking is what a person wants there anyway. */
.card .row { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0; color: var(--ink-soft); }
.card .row .label { min-width: 4.5em; max-width: 100%; color: var(--ink-soft); }
.card .row .value { min-width: 0; }
.card .row .value { color: var(--ink); }

/* A whole card that is one tap target. */
a.card {
  display: block;
  text-decoration: none;
  color: inherit;
}
a.card:hover { border-color: var(--brand); }
a.card:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }

/* ------------------------------------------------------------------ status */
/* The word carries the meaning; the mark and the colour only reinforce it. */
.state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
}
.state::before { font-size: 1rem; }
.state.good { background: var(--good-soft); color: var(--good); }
.state.good::before { content: "✓"; }
.state.wait { background: var(--wait-soft); color: var(--wait); }
.state.wait::before { content: "⏳"; }
.state.stop { background: var(--stop-soft); color: var(--stop); }
.state.stop::before { content: "✕"; }
.state.info { background: var(--brand-soft); color: var(--brand); }
.state.info::before { content: "•"; }

/* ----------------------------------------------------------------- buttons */
.button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--tap);
  padding: 14px 20px;
  border: 2px solid transparent;
  border-radius: var(--radius);
  background: var(--brand);
  color: var(--brand-ink);
  font: inherit;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.button:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.button.secondary {
  background: transparent;
  color: var(--brand);
  border-color: var(--brand);
}
.button.danger { background: var(--stop); color: #fff; }
.button + .button { margin-top: 12px; }
.button[disabled] { opacity: 0.55; cursor: not-allowed; }

.button-note {
  margin: 10px 2px 0;
  color: var(--ink-soft);
  font-size: 0.95rem;
  text-align: center;
}

/* The main action stays reachable without scrolling back up. */
.actions { margin-top: 24px; }

/* ------------------------------------------------------------------- forms */
label {
  display: block;
  margin: 0 0 8px;
  font-weight: 600;
}
.field { margin: 0 0 20px; }
/* A group of radios is a `fieldset` with a `legend`, because that is what tells a
   screen reader that five options answer one question — without it each radio is
   announced with no idea what it belongs to. Three templates were resetting the
   browser's fieldset chrome with the same four inline declarations each, so the
   reset lives here and the markup is just `class="choices"`. The 24px box is the
   same tap target the rest of this stylesheet uses: a 13px default radio on a phone
   is a control that gets missed. */
.choices { border: 0; padding: 0; margin: 0 0 20px; }
.choices > legend { font-weight: 600; padding: 0; margin-bottom: 8px; }
.choices label { display: flex; gap: 12px; align-items: flex-start; font-weight: 400; }
.choices input[type="radio"] { width: 24px; height: 24px; margin-top: 4px; flex: none; }
.choices p { margin: 0 0 8px; }

/* The dashboard's bar list. One series over time, so one hue and no legend — the
   heading names it. The figure is written beside every bar, which is also the table
   view: nothing here is encoded by colour alone, and a screen reader gets the numbers
   rather than a decorative div. `--brand` is the product's own accent, already
   contrast-checked in both themes by the suite, so the bars need no new colour.

   No canvas and no chart library: this screen has to open with no signal, in two
   writing directions. A CSS width does both. The track is `--brand-soft` so an empty
   month is visibly an empty month and not a missing row, and `inline-size` rather
   than `width` so the bars grow from the start edge in Hebrew and Arabic alike. */
.bars { margin: 0; padding: 0; list-style: none; }
.bars > li { margin: 0 0 14px; }
.bars .when { display: block; color: var(--ink-soft); font-size: 0.95rem; margin-bottom: 4px; }
.bars .track {
  display: flex;
  align-items: center;
  gap: 10px;
}
.bars .fill {
  background: var(--brand);
  /* 4px rounded data-end, anchored flat against the baseline it grows from. */
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  border-start-end-radius: 4px;
  border-end-end-radius: 4px;
  block-size: 14px;
  min-inline-size: 0;
}
.bars .rail { flex: 1; background: var(--brand-soft); block-size: 14px; border-radius: 4px; }
.bars .figure { font-weight: 700; white-space: nowrap; }

/* The hero figure: the one number the screen leads with. */
.hero { font-size: 2.6rem; line-height: 1.1; font-weight: 700; margin: 4px 0 0; }
.tiles { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 8px; }
.tiles > div { flex: 1 1 8.5rem; min-inline-size: 0; }
.tiles .value { font-size: 1.5rem; font-weight: 700; display: block; }
.tiles .name { color: var(--ink-soft); font-size: 0.9rem; }
.field .hint { margin: 6px 0 0; color: var(--ink-soft); font-size: 0.95rem; }

input[type="tel"],
input[type="text"],
textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 13px 14px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font: inherit;
}
input:focus,
textarea:focus {
  border-color: var(--brand);
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}
input.code {
  font-size: 1.9rem;
  letter-spacing: 0.35em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Two fields or two buttons side by side, stacking on a narrow screen. */
.pair { display: flex; gap: 12px; }
.pair > * { flex: 1; min-width: 0; }
@media (max-width: 360px) { .pair { flex-direction: column; } }

select,
input[type="date"],
input[type="time"],
input[type="number"] {
  width: 100%;
  min-height: var(--tap);
  padding: 13px 14px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  font: inherit;
}
select:focus,
input[type="date"]:focus,
input[type="time"]:focus,
input[type="number"]:focus {
  border-color: var(--brand);
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* ------------------------------------------------------------------ notices */
.notice {
  display: flex;
  gap: 12px;
  padding: 16px;
  border-radius: var(--radius);
  margin: 0 0 18px;
  border: 1px solid transparent;
}
.notice .mark { font-size: 1.3rem; line-height: 1.2; }
.notice.problem { background: var(--stop-soft); color: var(--stop); border-color: var(--stop); }
/* It takes focus when it appears, so it needs a ring like anything else that does —
   and `tabindex="-1"` would otherwise give it one that never shows. */
.notice.problem:focus { outline: 3px solid var(--stop); outline-offset: 3px; }
.notice.problem:focus:not(:focus-visible) { outline-offset: 2px; }
.notice.calm { background: var(--brand-soft); color: var(--ink); border-color: var(--line); }

/* The network banner. It sits above everything because it changes what the rest of
 * the screen means: a page read from the device is not a page read from the council.
 */
.offline-bar {
  padding: 12px var(--gap);
  text-align: center;
  font-weight: 600;
  font-size: 0.95rem;
  background: var(--wait-soft);
  color: var(--wait);
}
.offline-bar[data-tone="pending"] { background: var(--brand-soft); color: var(--brand); }
.offline-bar[data-tone="sent"] { background: var(--good-soft); color: var(--good); }
/* The refresh the banner offers when it will not refresh on its own. A real button,
   so the keyboard reaches it, and tall enough to hit with a thumb. */
.offline-bar button {
  min-height: var(--tap-small);
  padding: 0 14px;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

/* A decision kept on the phone and not yet known to the council. */
.state.held { background: var(--wait-soft); color: var(--wait); }
.state.held::before { content: "⇡"; }

/* ------------------------------------------------------------------ results */
.result { text-align: center; padding: 34px 0 10px; }
.result .mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The circle is in `rem` because the glyph inside it is: at 200% text the glyph was
     2.6rem — 83px — inside a fixed 84px circle, and the top and bottom of it were cut
     off. A badge that scales with its own contents cannot clip them. */
  width: 5.25rem;
  height: 5.25rem;
  border-radius: 50%;
  background: var(--good-soft);
  color: var(--good);
  font-size: 2.6rem;
  margin: 0 0 18px;
}
.result.wait .mark { background: var(--wait-soft); color: var(--wait); }
.result h1 { margin: 0 0 12px; }

/* -------------------------------------------------------------------- misc */
.total {
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.2;
  margin: 0 0 6px;
}
.list { list-style: none; margin: 0; padding: 0; }
.list li { padding: 14px 0; border-bottom: 1px solid var(--line); }
.list li:last-child { border-bottom: 0; }
/* A label on one side and what you can do about it on the other — until the two no
   longer fit side by side. At 250% text "מנהל מחלקה" and "הסירו" together are wider
   than the card, and the row pushed the page 4px sideways rather than letting them
   stack. `wrap` is the whole fix; `min-width: 0` lets a long label break instead of
   setting the row's width by itself. */
.spread {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: baseline;
  flex-wrap: wrap;
}
.spread > * { min-width: 0; }

nav.tabs {
  /* `sticky`, not `fixed`. A fixed bar is outside the flow, so the page has to guess
     how much room to leave for it — and the guess was a fixed 6rem, while the bar at
     200% text is 204px tall and at 250% is 480px. Measured: it covered the last 241px
     of the page. A sticky bar keeps its own space at the end of the document and
     floats over whatever scrolls past it before then, which is what the fixed one was
     pretending to do. */
  position: sticky;
  inset-inline: 0;
  bottom: 0;
  z-index: 5;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding: 6px max(var(--gap), env(safe-area-inset-left))
    max(6px, env(safe-area-inset-bottom)) max(var(--gap), env(safe-area-inset-right));
}
nav.tabs ul {
  max-width: 560px;
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: flex;
  /* Four labelled tabs do not fit across 320px once the text is at 250%, and a label
     is not decoration — it is how a person knows what the tab is. So the row wraps
     instead of being cut off or shrunk back down. The gap `.shell` leaves is in `rem`
     and grows with the same text, so a bar on two rows is still clear of the content
     underneath it. */
  flex-wrap: wrap;
}
/* `flex: 1` is `flex: 1 1 0%`: every tab asks for nothing, so four of them always fit
   across any width and the wrap declared above could never happen. It didn't — at 200%
   text, the size WCAG 1.4.4 asks about, two of the four labels were cut off inside a
   72px cell, and at 250% all four were. Measured, after the round that wrote the
   comment about wrapping.

   The basis is in `em`, so it is the width of about four characters of whatever size
   the person is reading at: four tabs across at normal text, two at 200%, one at 250%.
   `min-width: 0` stays, so a long label wraps inside its cell rather than widening the
   page. */
nav.tabs li { flex: 1 1 4em; min-width: 0; }
nav.tabs a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-height: var(--tap);
  justify-content: center;
  padding: 4px;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.8rem;
  font-weight: 600;
}
nav.tabs a[aria-current="page"] { color: var(--brand); }


nav.tabs .glyph { font-size: 1.35rem; line-height: 1; }

@media (prefers-reduced-motion: no-preference) {
  a, .button { transition: background-color 120ms ease, border-color 120ms ease; }
}

/* A legal text is read, not skimmed: wider line height, and a cap on the measure so
   a long paragraph does not run the full width of a tablet. */
.document { line-height: 1.75; max-width: 62ch; }
.document p { margin: 0 0 12px; }

/* The native file input draws its own button, and the browser labels that button in
   the browser's language — "Choose File", in English, in the middle of a Hebrew
   screen that a council clerk is reading. Nothing in HTML or CSS can translate it, so
   the control is taken out of the page's flow and a label we do write stands in for
   it. Clicking the label opens the picker exactly as the input would, with no
   JavaScript involved. */
.file-field input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
}
.file-field .button { display: inline-flex; cursor: pointer; }
.file-field input[type="file"]:focus-visible + .button { outline: 3px solid var(--brand); }
.file-name { margin: 10px 0 0; color: var(--ink-soft); font-size: 0.95rem; }

/* ------------------------------------------------------------------- paper
   A council prints the monthly hours to take to a meeting, and the stylesheet had
   no print rules at all. Two things follow from that, both measured.

   A printer drops background colours unless the person goes and turns them on. The
   header's text is white *because* it sits on teal, so on paper it is white on white:
   measured at 1:1 contrast. The one line that says whose sheet this is — the council's
   own name — was the line that disappeared.

   And everything built for a screen printed too: the bottom bar, the skip link, the
   language switch, the buttons. Ink spent on controls that cannot be pressed.

   Backgrounds are not forced back on here. That would fight the person's own printer
   settings and spend their toner; making the text dark costs nothing and works
   whichever way those settings are set. */
@media print {
  body {
    display: block;
    min-height: 0;
    background: #fff;
    color: #000;
  }
  /* The council's name stays — it is what the sheet is of — as ink rather than as
     white text on a colour that will not be there. */
  header.bar {
    background: none;
    color: #000;
    border-bottom: 1px solid #999;
  }
  header.bar .bar-tools,
  nav.tabs,
  a.skip,
  .offline-bar,
  .actions,
  button,
  .button {
    display: none;
  }
  .shell {
    max-width: none;
    padding: 0;
  }
  .card {
    border: 1px solid #999;
    box-shadow: none;
    background: none;
    /* A table of hours split across a page break is a table somebody has to
       reassemble by hand. */
    break-inside: avoid;
  }
  h1, h2, h3 { break-after: avoid; }
  .quiet, .hint, .lead { color: #333; }
}
