/*
  ECPS Facilities — read one-handed, at arm's length, in a bright gym or a dim
  mechanical room. Design rules that follow from that:

    * Light background, not dark. Half this work happens outdoors or under gym
      lights where a dark UI washes out completely.
    * Colour carries exactly one meaning: how soon this is due. Nothing else on
      the page is coloured, so the rails are unmissable.
    * One loud element per card — the countdown. Everything around it is quiet.
    * Every action target clears 48px and sits in the thumb zone.
*/

:root {
  --ink: #16181d;
  --ink-2: #3d434b;

  /* The one customizable colour: the app bar's ground. Overridden by an inline
     custom property in scheduling/base.html when a district has set one, which
     is why the value here is only a fallback and why nothing else may read it.

     It is deliberately separate from --ink even though they start out the same.
     --ink is body text, button fills and rules; rebranding by changing --ink
     would repaint the words on the page. */
  --brand: #16181d;
  --muted: #6c737b;
  --paper: #eceeed;
  --surface: #ffffff;
  --rule: #d2d7d4;

  --overdue: #a4231b;
  --today: #a35c00;
  --soon: #2b5f8f;
  --scheduled: #4a5560;
  --done: #838a90;

  --pad: 16px;
  --radius: 4px;
  --tap: 48px;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
  padding-bottom: calc(88px + env(safe-area-inset-bottom));
}

a { color: inherit; }

/* ---- Page watermark ----------------------------------------------------

   The district mark, faint, behind everything. Only drawn when one has been
   uploaded -- base.html emits neither the element nor --page-mark otherwise.

   Fixed and centred rather than tiled or scrolling: a repeating pattern behind
   a task board is visual noise competing with the rails, and one that scrolls
   drags the eye down a list somebody is scanning for a countdown.

   7% is deliberately almost-nothing. The cards are opaque, so on a busy board
   this shows only in the margins, which is where a watermark belongs. If it
   wants to be stronger, this is the one number to change -- but the board has
   to stay readable at arm's length in a bright gym, and that is what is being
   traded against. */
.page-mark {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--page-mark);
  background-repeat: no-repeat;
  background-position: center 58%;
  background-size: min(76vw, 460px) auto;
  opacity: 0.07;
}

/* Lifts the page above the watermark. Everything else that stacks -- the bar at
   20, the day headers at 15, the action bar at 30 -- is either inside this or
   outside and higher, so one step is enough. */
.wrap { position: relative; z-index: 1; }

/* ---- App bar ---------------------------------------------------------- */

.bar {
  position: sticky;
  top: 0;
  z-index: 20;
  /* The only place --brand is read. Keep it that way: the moment a second
     element takes its colour from here, "brand" becomes a meaning that colour
     carries, and colour in this app already has exactly one. */
  background: var(--brand);
  color: #fff;
  padding: calc(env(safe-area-inset-top) + 12px) var(--pad) 12px;
}

.bar__eyebrow {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* White at reduced opacity rather than a fixed grey. The old #9aa2ab was
     chosen against a near-black bar and only worked there: on a mid-tone brand
     colour it fell to 2.6:1 and the district name became unreadable, which was
     the real reason a legitimate school colour was being refused. An alpha
     scales with whatever ground is chosen, so the check on save is about the
     colour and not about a grey that assumed one. 0.62 lands within a shade of
     the old value on the stock bar. */
  color: rgb(255 255 255 / 0.62);
  margin: 0 0 2px;
  /* Flex so an uploaded mark sits on the baseline of the district name rather
     than pushing the line taller. */
  display: flex;
  align-items: center;
  gap: 8px;
}

.bar__mark {
  /* Small and quiet. The countdown is the one loud element on a card, and a
     crest large enough to compete with it would cost the board the thing that
     makes it readable at arm's length. Height only, width auto, so a mark that
     is not quite square is not squashed. */
  height: 20px;
  width: auto;
  flex: none;
}


.bar__title {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.bar__stat {
  margin-top: 6px;
  font-size: 13px;
  /* Same reasoning as the eyebrow, a shade brighter because this line carries
     the counts somebody actually reads. */
  color: rgb(255 255 255 / 0.74);
  font-variant-numeric: tabular-nums;
}

.bar__stat b { color: #ff8d84; font-weight: 700; }

/* ---- The bar's menu ----------------------------------------------------

   Parked in the bar's top-right, deliberately *not* in the thumb-zone action
   bar at the bottom. That bar is for the one thing the current screen exists to
   do -- mark a task done, decide a request -- and it is where a thumb lands
   without looking. Navigating away is not what you came here for, and an
   accidental sign-out on a shared phone in a mechanical room costs somebody a
   fresh sign-in mid-job. Top-right is the awkward reach, which here is the
   point.

   .bar is position:sticky, so it is already a containing block and this needs
   no wrapper -- which matters, because wrapping .bar in a positioned div would
   confine the stickiness to that wrapper and the app bar would stop sticking. */
.nav {
  position: absolute;
  top: env(safe-area-inset-top);
  right: calc(var(--pad) - 12px);
}

.nav__toggle {
  /* Quiet. Colour in this app means how soon something is due, and nothing in
     a menu is due -- so this gets the same muted grey as the eyebrow it sits
     beside, no border and no fill. Full --tap box for the touch target, with
     the visible text much smaller than the box. */
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0 12px;
  color: #9aa2ab;
  font-size: 13px;
  cursor: pointer;
  list-style: none;          /* Firefox */
  user-select: none;
}

.nav__toggle::-webkit-details-marker { display: none; }   /* Safari */

.nav[open] .nav__toggle { color: #fff; }

.nav__panel {
  /* Anchored under the toggle rather than filling the screen. A full-height
     drawer would need a scrim, a scroll lock and a close button; this is nine
     rows at most and the page behind it is still the point. */
  position: absolute;
  right: 0;
  min-width: 15rem;
  max-width: calc(100vw - var(--pad) * 2);
  padding: 4px 0;
  background: var(--ink-2);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.4);
}

.nav__list { margin: 0; padding: 0; list-style: none; }

.nav__account {
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px solid rgb(255 255 255 / 0.14);
}

.nav__whoami {
  /* Quiet caption heading the account group, not a row: there is nowhere to go
     from it. Muted grey like the toggle, with the address itself in white so
     the thing you came to read is the thing you see. */
  margin: 0;
  padding: 10px 16px 6px;
  color: #9aa2ab;
  font-size: 12px;
  line-height: 1.35;
}

.nav__whoami b {
  display: block;
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  /* Addresses do not break at spaces because they have none. Without this a
     long one widens the panel past the screen instead of wrapping. */
  overflow-wrap: anywhere;
}

.nav__list form { margin: 0; }

.nav__item {
  /* Link and form-button rows have to be indistinguishable: which HTTP verb the
     destination happens to want is not something the user should be able to
     see. Everything that differs between <a> and <button> is reset here. */
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: var(--tap);
  padding: 0 16px;
  background: none;
  border: 0;
  color: #fff;
  font: inherit;
  font-size: 15px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.nav__item:active { background: rgb(255 255 255 / 0.10); }

.nav__label { flex: 1; }

/* The screen you are already on. Weight and a tick, not colour -- and read from
   aria-current so the announced state and the drawn state cannot drift. */
.nav__item[aria-current="page"] { font-weight: 700; }
.nav__item[aria-current="page"]::after { content: "✓"; color: #9aa2ab; }

.nav__count {
  /* Plain, never a coloured badge. "3 waiting" is a quantity, not a deadline,
     and colour here would be the second meaning this design does not allow. */
  color: #9aa2ab;
  font-variant-numeric: tabular-nums;
}

/* Keep a long title from running underneath the toggle. Scoped with :has() so
   that the bars on signed-out screens, where the menu renders nothing at all,
   keep their full width instead of carrying a permanent gutter. */
.bar:has(.nav) .bar__eyebrow,
.bar:has(.nav) .bar__title { padding-right: 76px; }

/* ---- Filters ---------------------------------------------------------- */

.filters {
  position: sticky;
  top: 0;
  z-index: 15;
  display: flex;
  gap: 8px;
  padding: 10px var(--pad);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
  scrollbar-width: none;
}
.filters::-webkit-scrollbar { display: none; }

.chip {
  flex: 0 0 auto;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  padding: 0 16px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}

.chip[aria-current="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

/* ---- Day headers ------------------------------------------------------
   Grouping by the day the work happens, because that is how a crew plans.
   The order carries real information, so it earns a structural device.      */

.day {
  position: sticky;
  top: 61px;
  z-index: 10;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 14px var(--pad) 6px;
  background: linear-gradient(var(--paper) 72%, transparent);
}

.day__label {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.day__count {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ---- Task card -------------------------------------------------------- */

.card {
  position: relative;
  display: block;
  margin: 0 var(--pad) 10px;
  padding: 14px 14px 14px 26px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
}

.card:active { background: #f6f7f7; }

/* The rail: a colour band whose fill drains as the due time approaches. The
   band alone says "how urgent"; the fill says "how much runway is left". Both
   readable without focusing on any text.                                    */

.rail {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 10px;
  background: #e4e7e6;
  border-radius: var(--radius) 0 0 var(--radius);
  overflow: hidden;
}

.rail__fill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--band, var(--scheduled));
}

.card[data-band="overdue"] { --band: var(--overdue); }
.card[data-band="today"]   { --band: var(--today); }
.card[data-band="soon"]    { --band: var(--soon); }
.card[data-band="scheduled"] { --band: var(--scheduled); }
.card[data-band="done"]    { --band: var(--done); }

.card[data-band="overdue"] .rail__fill,
.card[data-band="done"] .rail__fill { top: 0; }

.card__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

/* The one loud thing on the page. */
.countdown {
  flex: 0 0 auto;
  text-align: right;
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  color: var(--band, var(--scheduled));
}

.countdown small {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.card__facility {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.card__event {
  margin: 2px 0 0;
  font-size: 14px;
  color: var(--ink-2);
}

.card__when {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.card__items {
  margin: 10px 0 0;
  padding: 10px 0 0;
  border-top: 1px solid var(--rule);
  list-style: none;
  font-size: 14px;
}

.card__items li { display: flex; gap: 8px; padding: 2px 0; }
.card__items b { font-variant-numeric: tabular-nums; }

.flag {
  display: inline-block;
  margin-top: 8px;
  padding: 3px 8px;
  border-radius: 3px;
  background: #eef0ef;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* ---- Detail ----------------------------------------------------------- */

.sheet {
  margin: var(--pad);
  padding: var(--pad);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.sheet h2 {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.kv { display: grid; grid-template-columns: 108px 1fr; gap: 6px 12px; font-size: 15px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; font-weight: 600; }

.checklist { margin: 0; padding: 0; list-style: none; }

.checklist li {
  display: flex;
  gap: 12px;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 16px;
}
.checklist li:last-child { border-bottom: 0; }
.checklist .qty {
  flex: 0 0 auto;
  min-width: 34px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

textarea {
  width: 100%;
  min-height: 88px;
  padding: 12px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font: inherit;
  resize: vertical;
}

/* ---- Actions ---------------------------------------------------------- */

.actions {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  gap: 10px;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  background: rgba(236, 238, 237, 0.94);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--rule);
}

.btn {
  flex: 1;
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 18px;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

.btn--primary { background: var(--ink); color: #fff; }
.btn--danger { background: var(--surface); border-color: var(--overdue); color: var(--overdue); }
.btn:disabled { opacity: 0.45; }

/* ---- Messages / empty ------------------------------------------------- */

.msg {
  margin: 12px var(--pad);
  padding: 12px 14px;
  border-left: 4px solid var(--ink);
  background: var(--surface);
  font-size: 15px;
}
.msg.error { border-color: var(--overdue); }
.msg.success { border-color: #2f7a52; }

.empty {
  margin: 48px var(--pad);
  text-align: center;
  color: var(--muted);
}
.empty p { margin: 0 0 4px; font-size: 17px; font-weight: 600; color: var(--ink-2); }
.empty span { font-size: 14px; }

/* ---- Submission wizard -------------------------------------------------
   A calmer register of the same system. Community-facing, used once or twice a
   year by someone who has never seen it, usually sitting down.

   The rule that matters: no urgency colour appears anywhere below. Colour still
   means exactly one thing in this app -- how soon something is due -- and
   nothing in a form is due. The step trail, the selected states, and the
   emphasis are all ink and weight. Red appears only on a field that is actually
   wrong, which is the same use .msg.error already makes of it.
------------------------------------------------------------------------- */

.bar--calm { padding-bottom: 12px; }

/* Step trail. Deliberately quiet -- it orients, it does not compete. */
.trail {
  display: flex;
  gap: 4px;
  margin: 0;
  padding: 10px var(--pad) 14px;
  list-style: none;
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
  scrollbar-width: none;
}
.trail::-webkit-scrollbar { display: none; }
.trail__step { flex: 0 0 auto; font-size: 14px; }
.trail__step a, .trail__step span { display: flex; align-items: center; gap: 6px; padding: 6px 10px; text-decoration: none; color: var(--muted); white-space: nowrap; }
.trail__step a { color: var(--ink-2); }
.trail__num {
  display: inline-grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.trail__step[data-state="current"] > span { color: var(--ink); font-weight: 700; }
.trail__step[data-state="current"] .trail__num { background: var(--ink); border-color: var(--ink); color: #fff; }
.trail__step[data-state="done"] .trail__num { background: var(--ink-2); border-color: var(--ink-2); color: #fff; }

/* Explanatory copy. The board has almost none; this screen leans on it. */
.lede { margin: 14px var(--pad) 0; color: var(--ink-2); font-size: 15px; }
.lede p { margin: 0 0 8px; }

.note {
  margin: 12px var(--pad);
  color: var(--muted);
  font-size: 14px;
}

.sheet__note { margin: 10px 0 0; color: var(--muted); font-size: 14px; }
.sheet__count { color: var(--muted); font-weight: 400; }
.sheet--bad { border-left: 4px solid var(--overdue); }

.problems { margin: 0; padding-left: 18px; font-size: 15px; }
.problems li { margin: 4px 0; }

/* ---- Form fields ------------------------------------------------------- */

.field { margin: 0 0 16px; }
.field > label {
  display: block;
  margin-bottom: 5px;
  font-size: 15px;
  font-weight: 600;
}
.field__help { margin: 5px 0 0; color: var(--muted); font-size: 13px; }
.field__error { margin: 5px 0 0; color: var(--overdue); font-size: 13px; font-weight: 600; }
.field--bad > label { color: var(--overdue); }

/* password was missing here until there was a login form to need it, which is
   why it is worth stating: an input type absent from this list gets no width,
   no 48px height, and the browser's own border. */
input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="date"], input[type="time"], input[type="file"], input[type="password"],
select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.field--bad input, .field--bad select, .field--bad textarea { border-color: var(--overdue); }

/* Checkboxes get the full 48px row, not just the 20px box -- this is still a
   phone screen even when it is a form. */
.check {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--tap);
  font-size: 16px;
  cursor: pointer;
}
.check input[type="checkbox"] { width: 22px; height: 22px; flex: 0 0 auto; accent-color: var(--ink); }
.check--lead { font-weight: 600; }
.check--lead small { display: block; font-weight: 400; font-size: 13px; color: var(--muted); }
.field--check { margin-bottom: 10px; }

/* Radio group. Borrows .check's row so a radio and a checkbox are the same
   48px target and the same type -- the only difference is which one the
   browser draws. accent-color is --ink for the same reason the weekday
   toggles have none: a selected state here is not urgency, and colour in this
   app means how soon something is due. */
.radios { margin: 0 0 10px; }
.radios .check input[type="radio"] {
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  accent-color: var(--ink);
}

.field-row { display: flex; gap: 12px; }
.field-row .field { flex: 1; }

/* Weekday toggles. Same 48px target, no colour. */
.days { display: flex; flex-wrap: wrap; gap: 6px; }
.day-toggle {
  position: relative;
  display: grid;
  place-items: center;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0 8px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 14px;
  cursor: pointer;
}
.day-toggle input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.day-toggle:has(input:checked) { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 700; }
.day-toggle:has(input:focus-visible) { outline: 3px solid var(--soon); outline-offset: 2px; }

/* ---- Setup options ----------------------------------------------------- */

.opt { padding: 10px 0; border-bottom: 1px solid var(--rule); }
.opt:last-child { border-bottom: 0; }
.opt--bad { border-left: 3px solid var(--overdue); padding-left: 10px; }
.opt__detail { display: none; gap: 8px; padding: 0 0 6px 34px; }
.opt__detail label { font-size: 13px; color: var(--muted); }
/* Only ask for a quantity once the thing itself is wanted. */
.opt:has(.check input:checked) .opt__detail { display: block; }
.opt__detail input[type="number"] { max-width: 140px; }

/* ---- Dates already added ----------------------------------------------- */

.block { padding: 10px 0; border-bottom: 1px solid var(--rule); }
.block:last-child { border-bottom: 0; }
.block__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.block__facility { margin: 0; font-weight: 700; }
.block__building { margin: 0 0 6px; color: var(--muted); font-size: 14px; }

.dates { margin: 0; padding: 0; list-style: none; font-size: 15px; }
.dates li { display: flex; align-items: center; gap: 12px; padding: 0; }
.dates__day { font-weight: 600; }
.dates__time { color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Pushes the remove control to the right edge and leaves the day and time
   sitting together on the left. space-between would spread all three. */
.dates__form { margin-left: auto; }
/* Quiet on purpose. Removing one date from a draft is not urgent and not
   dangerous -- the loud .link-danger above it clears the whole space -- so this
   is ink and an underline, no colour. Full tap height even though the text is
   small, because the row is read one-handed like everything else. */
.dates__remove {
  min-height: var(--tap);
  padding: 0 8px;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  text-decoration: underline;
  cursor: pointer;
}

.estimate { margin: 0; font-size: 30px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---- Wizard actions ----------------------------------------------------
   Not the board's fixed thumb-zone bar. This screen is read top to bottom and
   the button belongs after what it acts on, not floating over it. */

/* A column with a gap, rather than plain block flow, because several of the
   account screens offer two buttons -- "sign in" beside "send a new link" -- and
   two 100%-wide inline-flex buttons in block flow sit flush against each other
   with only the collapsed whitespace between them. One child renders
   identically either way, which is every wizard step. */
.wizard-actions { display: flex; flex-direction: column; gap: 12px; margin: 16px var(--pad); }
.wizard-actions .btn { width: 100%; }
/* Direction only: display and gap are inherited from the rule above now, and
   restating display:flex here without a direction would leave this as a column. */
.wizard-actions--split { flex-direction: row; }
.wizard-actions--split .btn { flex: 1; }

.discard { margin: 24px var(--pad) 8px; text-align: center; }
.link-danger {
  min-height: var(--tap);
  padding: 0 8px;
  border: 0;
  background: none;
  color: var(--overdue);
  font: inherit;
  font-size: 14px;
  text-decoration: underline;
  cursor: pointer;
}

/* ---- Entrance screens --------------------------------------------------
   Sign in, sign up, password reset. allauth's views wearing this design
   system instead of its stock templates.

   Same calm register as the wizard, for the same reason: nothing on a login
   form is due, so no urgency colour appears here. Red is reserved for a field
   that is genuinely wrong, which is the one use .field__error already makes
   of it.

   Why this screen gets care disproportionate to its size: it is the first
   thing a community requester sees, usually arriving from a link in an email,
   before they have any reason to believe this is really the district's
   system. A login page that looks like a default login page is exactly what a
   phishing page looks like. Looking continuous with the pages it leads to is
   the point, not decoration.
------------------------------------------------------------------------- */

/* A quiet rule with a word in it, between the password form and any
   third-party sign-in. Ink and weight, never colour. */
.or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px var(--pad);
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.or::before, .or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* allauth puts the password-reset link inside the password field's help text.
   That is the right place for it -- it is where someone looks when the password
   is the thing going wrong -- but 13px of muted body copy is not a target.
   Padded out to roughly a thumb without turning the help line into a button,
   and given weight so it reads as a link rather than as more help. */
.field__help a {
  display: inline-block;
  padding: 10px 4px;
  color: var(--ink-2);
  font-weight: 600;
}

/* Same treatment for links in quiet footer copy -- a real target without
   turning the line into a button, which would compete with the actual actions
   on the screen. */
.note a {
  display: inline-block;
  min-height: var(--tap);
  padding: 12px 4px;
  color: var(--ink-2);
  font-weight: 600;
}

/* ---- Larger screens ---------------------------------------------------- */

@media (min-width: 720px) {
  .wrap { max-width: 680px; margin: 0 auto; }
  .actions { position: static; background: none; backdrop-filter: none; border-top: 0; padding: 0 var(--pad) 32px; max-width: 680px; margin: 0 auto; }
  body { padding-bottom: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

:focus-visible { outline: 3px solid var(--soon); outline-offset: 2px; }

/* ---- Availability calendar ---------------------------------------------

   Calm register. **No urgency colour anywhere on this screen**, which is the
   rule doing the most work here: colour in this app means how soon something
   is due, and a grid where every booked cell carried the ramp would read as a
   month of emergencies and would cost the board the contrast it depends on.
   Booked cells are distinguished by ink and weight instead. The single
   exception is today's cell, which uses --brand as a tint -- a location marker,
   not a deadline.

   The month grid is a table because it is tabular. Seven columns will not fit
   event names on a phone, so narrow screens show a count per day and the week
   view carries the detail; both forms are in the markup and CSS picks one,
   because a calendar that needs script to be legible would not work on the
   offline shell. */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.calfilter { margin: 14px var(--pad) 0; }
.calfilter__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0;
}
.calfilter__label { font-size: 14px; color: var(--ink-2); font-weight: 600; }
.calfilter__select {
  flex: 1 1 200px;
  min-height: var(--tap);
  padding: 0 10px;
  font-size: 16px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.calfilter__go {
  min-height: var(--tap);
  padding: 0 18px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: var(--ink);
  border: 0;
  border-radius: var(--radius);
}

/* Paging. The arrows are the targets, so they clear 48px on their own rather
   than relying on the label beside them. */
.calnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 14px var(--pad) 0;
}
.calnav__label {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  text-align: center;
}
.calnav__step {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  min-width: var(--tap);
  justify-content: center;
  padding: 0 10px;
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
/* The word is the affordance on a wide screen and noise on a narrow one, where
   the chevron and position already say it. */
.calnav__word { display: none; }

.calswitch {
  display: flex;
  gap: 4px;
  align-items: center;
  margin: 10px var(--pad) 0;
  font-size: 15px;
}
.calswitch a,
.calswitch__on {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: var(--radius);
  text-decoration: none;
}
.calswitch__on { font-weight: 700; background: var(--surface); border: 1px solid var(--rule); }
.calswitch a { color: var(--ink-2); font-weight: 600; }
.calswitch__today { margin-left: auto; }

.cal {
  width: 100%;
  margin: 12px 0 0;
  border-collapse: collapse;
  table-layout: fixed;
  background: var(--surface);
}
.cal th {
  padding: 8px 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--rule);
}
.cal th abbr { text-decoration: none; }
.cal__cell {
  height: 62px;
  padding: 4px 2px;
  vertical-align: top;
  border: 1px solid var(--rule);
}
/* Days either side of the month. Present so the weeks are whole, quiet so they
   do not read as part of it. */
.cal__cell--outside { background: var(--paper); }
.cal__cell--outside .cal__date { color: var(--muted); }
.cal__cell--today { box-shadow: inset 0 0 0 2px var(--brand); }
.cal__date { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink-2); text-align: right; }

.cal__count {
  margin: 2px 0 0;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  color: var(--ink);
}
/* The names themselves are for wide screens; see the media query below. */
.cal__event { display: none; }

/* An entry is a link when the viewer can open the booking behind it, and a
   paragraph when they cannot. The two must look identical: the calendar codes
   urgency by colour and nothing else may introduce a second colour meaning, so
   a link here inherits the ink and drops the underline. The affordance is the
   pointer and the focus ring, which is enough on a page where tapping a
   booking is the obvious thing to try. */
a.cal__event,
.calweek__link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
a.cal__event:focus-visible,
.calweek__link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
/* The whole row is the target, not the words in it -- these screens are used
   one-handed and a 48px target is the rule everywhere else in the app. */
.calweek__link {
  display: block;
  min-height: 48px;
}

.calweek { margin: 12px 0 0; }
.calweek__day {
  padding: 12px var(--pad);
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}
.calweek__day--today { box-shadow: inset 3px 0 0 var(--brand); }
.calweek__head {
  margin: 0 0 6px;
  font-size: 15px;
  font-weight: 700;
}
.calweek__head small { font-weight: 400; color: var(--muted); margin-left: 6px; }
.calweek__list { margin: 0; padding: 0; list-style: none; }
.calweek__event { padding: 6px 0; border-top: 1px solid var(--rule); }
.calweek__when { display: block; font-size: 14px; font-variant-numeric: tabular-nums; }
.calweek__what { display: block; font-size: 16px; }
.calweek__where { display: block; font-size: 13px; color: var(--muted); }
.calweek__free { margin: 0; font-size: 14px; color: var(--muted); }

.calnote {
  margin: 14px var(--pad) 0;
  font-size: 13px;
  color: var(--muted);
}

/* ---- Calendar import ---------------------------------------------------- */

.importcount { margin: 0 0 10px; font-size: 15px; color: var(--ink-2); }
/* The log is the point of the screen, and its lines are long. Scrolls inside
   itself rather than widening the page. */
.importlog {
  margin: 0;
  padding: 10px;
  max-height: 340px;
  overflow: auto;
  font-size: 13px;
  line-height: 1.5;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  white-space: pre-wrap;
  word-break: break-word;
}
.importhint { margin: 10px 0 0; font-size: 14px; color: var(--ink-2); }
.importlist { margin: 0; padding: 0; list-style: none; }
.importlist li { padding: 8px 0; border-top: 1px solid var(--rule); }
.importlist li:first-child { border-top: 0; }
.importlist b { display: block; font-size: 15px; word-break: break-word; }
.importlist small { color: var(--muted); font-size: 13px; }

@media (min-width: 720px) {
  /* Room for the names, so the count gives way to the events themselves. */
  .cal__cell { height: 108px; }
  .cal__count { display: none; }
  .cal__event {
    display: block;
    margin: 3px 0 0;
    padding: 2px 4px;
    font-size: 12px;
    line-height: 1.3;
    background: var(--paper);
    border-left: 2px solid var(--scheduled);
    border-radius: 2px;
  }
  .cal__when { font-variant-numeric: tabular-nums; }
  .cal__what { display: block; }
  .cal__where { display: block; color: var(--muted); }
  .calnav__word { display: inline; }
}

/* ---- Help ---------------------------------------------------------------
   The calmest register in the app. It is the one screen that is pure prose,
   read start to finish by somebody who has never seen any of this before, and
   the only one a signed-out visitor can reach.

   No urgency colour appears below, and none may: colour means how soon
   something is due, and nothing on a help page is due. Emphasis is ink and
   weight throughout.

   Headings are the reason this block exists. `.sheet h2` is a 12px uppercase
   field label -- right above a list of dates on a crew card, wrong above three
   paragraphs of explanation -- so the two `.help` rules below restate it at a
   readable size. They sit at the end of the file deliberately: the specificity
   is identical to `.sheet h2`, so source order is what settles it, and moving
   this block above the detail section would silently give the labels back.
------------------------------------------------------------------------- */

.help h2 {
  margin: 0 0 10px;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}

.help h3 {
  margin: 20px 0 6px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}

.help p { margin: 0 0 10px; font-size: 15px; color: var(--ink-2); }
.help p:last-child { margin-bottom: 0; }

/* Contents. Every row is a real target rather than a line of text with a link
   in it -- this is the one part of the page used one-handed, by somebody
   looking for a single answer, and 15 close-packed links are unusable on a
   phone. */
.helptoc { margin: var(--pad); }
.helptoc ul { margin: 0; padding: 0; list-style: none; }
.helptoc li { border-top: 1px solid var(--rule); }
.helptoc li:first-child { border-top: 0; }
.helptoc a {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 8px 4px;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  color: var(--ink);
}

/* Numbered procedure. The number is set in its own column so a step that wraps
   to four lines stays aligned with the one above it -- these are read while
   doing the thing they describe. */
.steps { margin: 0; padding: 0 0 0 26px; }
.steps li { margin: 0 0 14px; font-size: 15px; color: var(--ink-2); }
.steps li:last-child { margin-bottom: 0; }
.steps li b { color: var(--ink); }

/* The aside inside a step: the caveat that would break the sentence if it were
   in it. Quieter, and on its own line so the step still reads as one
   instruction. */
.steps__note {
  display: block;
  margin-top: 4px;
  font-size: 14px;
  color: var(--muted);
}

.bullets { margin: 0; padding: 0 0 0 20px; }
.bullets li { margin: 0 0 10px; font-size: 15px; color: var(--ink-2); }
.bullets li:last-child { margin-bottom: 0; }
.bullets li b { color: var(--ink); }
