/* ==========================================================================
   Catechism System — family portal
   St. Martin de Porres

   This file adds the parent-facing shell. It defines no colours, no fonts and
   no spacing of its own: every value below is a variable already declared in
   app.css, so the portal a family reads and the roster a catechist reads stay
   the same piece of work. Changing a colour here is done by changing it there.

   Written mobile first. The plain rules are the phone; the media queries add
   the room a tablet and a computer have.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Two colours the official palette names but app.css never declared.

   The staff layout writes them by hand as literals in its own style block, so
   nothing was ever broken there. Declared here they become real variables for
   both portals, and the bar has one source of truth instead of two.
   -------------------------------------------------------------------------- */

:root {
  --masthead-text: #C6CFE2;
  --masthead-gold: #B9A574;
}

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

body.fam {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;              /* phone body; the desktop query lifts it */
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;           /* nothing may scroll sideways */
}

/* Held while the drawer is open. Without it the page behind scrolls under the
   menu and the reader loses their place. */
body.fam-locked { overflow: hidden; }

/* --------------------------------------------------------------------------
   The split shell and the column of sub-items.

   The staff layout carries these rules in its own <style> block rather than in
   app.css, so there is nothing shared to point at. They are restated here to
   the same numbers — 200px column, 24px gutter, sticky, laid down as a row of
   pills under 760px — so both portals look and behave alike without one
   depending on a file it does not own.
   -------------------------------------------------------------------------- */

.famshell { max-width: var(--max-width); margin: 0 auto; }

.famshell--split {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: var(--s5);
  padding: var(--s5) var(--s4) var(--s8);
  align-items: start;
}

.fampage { max-width: var(--max-width); margin: 0 auto; padding: var(--s5) var(--s4) var(--s8); }
.famshell--split .fampage { max-width: none; margin: 0; padding: 0; }

.famsidenav {
  position: sticky;
  top: var(--s4);
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.famsidenav__title {
  font-size: var(--t-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--slate-pale);
  font-weight: 700;
  margin: 0 0 var(--s2);
  padding: 0 var(--s3);
}

.famsidenav__item {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--t-small);
  color: var(--slate);
  text-decoration: none;
  padding: 8px var(--s3);
  border-radius: var(--radius-sm);
  border-left: 2px solid transparent;
}

.famsidenav__item:hover { background: var(--paper); color: var(--ink); }
.famsidenav__item.is-on {
  background: var(--paper);
  color: var(--ink);
  font-weight: 600;
  border-left-color: var(--ink);
}

@media (max-width: 760px) {
  .famshell--split { grid-template-columns: minmax(0, 1fr); gap: var(--s4);
                     padding: var(--s4) var(--s4) var(--s7); }
  .famsidenav { position: static; flex-direction: row; overflow-x: auto; gap: 4px;
                padding-bottom: var(--s2); -webkit-overflow-scrolling: touch;
                scrollbar-width: none; }
  .famsidenav::-webkit-scrollbar { display: none; }
  .famsidenav__title { display: none; }
  .famsidenav__item { white-space: nowrap; border-left: none; min-height: 44px;
                      background: var(--paper); border-radius: var(--radius-pill);
                      padding: 7px 14px; }
  .famsidenav__item.is-on { border-left: none; box-shadow: inset 0 0 0 1px var(--ink); }
}

@media (max-width: 560px) {
  .fampage         { padding: var(--s4) var(--s3) var(--s7); }
  .famshell--split { padding: var(--s4) var(--s3) var(--s7); }
}

/* --------------------------------------------------------------------------
   The envelope

   Lit when it is the open screen. When notices are waiting it turns white and
   carries the count beside it, in the parish gold rather than red: red in this
   system means something went wrong, and a cancelled class is not an error.

   Capped at 9+ so a family with three children and a busy week cannot stretch
   the bar.
   -------------------------------------------------------------------------- */

.fambell {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 44px;
  padding: 0 var(--s2);
  border-radius: var(--radius-sm);
  color: var(--masthead-text);
  text-decoration: none;
}

.fambell:hover { background: rgba(255, 255, 255, .10); color: #fff; }
.fambell:focus-visible { outline: 2px solid var(--masthead-gold); outline-offset: 2px; }
.fambell.is-on { background: rgba(255, 255, 255, .16); color: #fff; }
.fambell.has-unread { color: #fff; }

.fambell__count {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  min-width: 17px;
  height: 17px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--masthead-gold);
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   The bar
   -------------------------------------------------------------------------- */

.famhead {
  background: var(--ink);
  color: var(--masthead-text);
  position: sticky;
  top: 0;
  z-index: 200;
  padding-top: env(safe-area-inset-top);
}

.famhead__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--s2) var(--s3);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
  min-height: 52px;
}

.famhead__mark {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;                 /* lets the screen name truncate, not overflow */
  flex: 1;
}

/* The same treatment the staff bar gives it: small, letterspaced, upper case.
   One parish name, one look, whichever portal is open. */
.famhead__parish {
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--masthead-gold);
  line-height: 1.4;
}

/* Fixed, like the staff bar's own mark. Which screen is open is already said
   by the lit item in the menu; repeating it here adds a line and no meaning. */
.famhead__name {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: #fff;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.famhead__tools {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex: none;
  margin-left: auto;
}

/* --------------------------------------------------------------------------
   EN/ES

   Always in the same corner, always reading EN/ES in both languages, so a
   parent who cannot read the screen can still find the way out of it.
   -------------------------------------------------------------------------- */

.famlang { margin: 0; }

.famlang__btn {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--masthead-text);
  background: transparent;
  border: 1px solid rgba(198, 207, 226, .35);
  border-radius: var(--radius-pill);
  min-height: 44px;
  min-width: 60px;
  padding: 0 var(--s3);
  cursor: pointer;
}

.famlang__btn:hover { border-color: var(--masthead-gold); color: #fff; }
.famlang__btn:focus-visible { outline: 2px solid var(--masthead-gold); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   Menu button

   The same square button the staff side uses, and the same behaviour: the
   three bars fold into a cross while the drawer is open, so the control that
   opened it is the control that closes it. It rides above the drawer rather
   than under it — otherwise the only way back out is the dimmed area, which
   nobody discovers on a phone.

   One departure from the staff button: 44px rather than 38. The staff side is
   used at a desk; this one is used with a thumb, in a car park, in a hurry.
   -------------------------------------------------------------------------- */

.famburger {
  display: none;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  place-items: center;
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: var(--radius-sm);
  color: #fff;
  cursor: pointer;
}

.famburger:hover { background: rgba(255, 255, 255, .18); }
.famburger:focus-visible { outline: 2px solid var(--masthead-gold); outline-offset: 2px; }

.famburger__bars,
.famburger__bars::before,
.famburger__bars::after {
  display: block;
  width: 17px;
  height: 1.8px;
  background: currentColor;
  border-radius: 2px;
  margin: 0 auto;
  transition: transform .16s ease, opacity .12s ease;
}

.famburger__bars { position: relative; }
.famburger__bars::before,
.famburger__bars::after { content: ''; position: absolute; left: 0; }
.famburger__bars::before { top: -5.5px; }
.famburger__bars::after  { top:  5.5px; }

.famburger[aria-expanded="true"] .famburger__bars { background: transparent; }
.famburger[aria-expanded="true"] .famburger__bars::before { transform: translateY(5.5px)  rotate(45deg); }
.famburger[aria-expanded="true"] .famburger__bars::after  { transform: translateY(-5.5px) rotate(-45deg); }

/* --------------------------------------------------------------------------
   Drawer

   A column that comes in from the right edge, dark, over everything. It does
   not push the bar taller and the page underneath does not move, so closing it
   returns the reader exactly where they were.

   Closed, it is off the canvas entirely: nothing dimmed, nothing locked, the
   page fully readable.
   -------------------------------------------------------------------------- */

.famscrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 150;
  background: rgba(11, 18, 34, .5);
  opacity: 0;
  transition: opacity .22s ease;
}
.famscrim.is-lit { opacity: 1; }
.famscrim[hidden] { display: none !important; }

.famdrawer {
  display: flex;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 200;
  width: min(78vw, 290px);
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  background: #16233F;
  border-left: 1px solid rgba(255, 255, 255, .14);
  padding: calc(var(--s5) + 8px) var(--s4) var(--s5);
  box-shadow: -16px 0 34px rgba(11, 18, 34, .38);
  transform: translateX(100%);
  transition: transform .22s ease;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.famdrawer.is-open { transform: translateX(0); }

/* Whose session this is, answered before the thumb travels anywhere. */
.famdrawer__top {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  padding: 0 12px var(--s4);
  margin: 0 0 var(--s2);
  border-bottom: 1px solid rgba(255, 255, 255, .14);
}

.famdrawer__who  { margin: 0; font-size: 16px; font-weight: 600; color: #fff; }
.famdrawer__role { margin: 2px 0 0; font-size: 11px; letter-spacing: .1em;
                   text-transform: uppercase; color: #8FA0C4; font-weight: 600; }

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

.famdrawer__item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: 11px 12px;
  color: #C6CFE2;
  text-decoration: none;
  font-family: var(--font-ui);
  font-size: 15px;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  text-align: left;
  cursor: pointer;
}

.famdrawer__item:hover { background: rgba(255, 255, 255, .10); color: #fff; }
.famdrawer__item.is-on { background: rgba(255, 255, 255, .16); color: #fff; font-weight: 600; }

.famdrawer__out {
  width: 100%;
  margin: var(--s4) 0 0;
  padding-top: var(--s3);
  border-top: 1px solid rgba(255, 255, 255, .14);
}

.famdrawer__item--out { color: #8FA0C4; }
.famdrawer__item--out:hover { background: rgba(255, 255, 255, .10); color: #fff; }

/* --------------------------------------------------------------------------
   Student switcher

   An account with one child never sees it. With two or more it is the first
   thing under the greeting, because reading the wrong child's attendance is
   worse than not reading any.
   -------------------------------------------------------------------------- */

.famkids {
  display: flex;
  gap: var(--s2);
  overflow-x: auto;
  padding: var(--s1) 0 var(--s3);
  margin: 0 0 var(--s3);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.famkids::-webkit-scrollbar { display: none; }

.famkid {
  flex: none;
  min-height: 44px;
  padding: var(--s2) var(--s4);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  color: var(--slate);
  font-family: var(--font-ui);
  font-size: 14px;
  white-space: nowrap;
  cursor: pointer;
}

.famkid.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   Cards and small parts
   -------------------------------------------------------------------------- */

.famcard {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: var(--s4);
  margin-bottom: var(--s3);
}

.famcard__head {
  margin: 0 0 var(--s3);
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--rule-soft);
}

.famcard__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  line-height: 1.2;
}

/* Numbers, dates and times are monospaced everywhere, so a digit is never
   misread and a column of them lines up. */
.famdata {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}

.famrubric {
  display: block;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--rubric);
  margin-bottom: var(--s1);
}

.famgreet {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  margin: var(--s2) 0 var(--s3);
  line-height: 1.2;
}

.famfacts {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3);
  margin: 0;
}

.famfacts dt {
  font-size: 13px;
  color: var(--slate-pale);
  margin: 0 0 2px;
}

.famfacts dd {
  margin: 0;
  font-size: 15px;
  color: var(--ink);
}

.famempty {
  text-align: center;
  padding: var(--s6) var(--s4);
}

.famempty__title {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  margin: 0 0 var(--s2);
}

.famempty__body {
  margin: 0 auto;
  max-width: 46ch;
  color: var(--slate);
  font-size: 15px;
}

/* Every state carries a word as well as a colour, so it survives a monochrome
   screen and a reader who does not distinguish the two. */
.famstate {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  padding: 3px var(--s2);
  border-radius: var(--radius-pill);
  font-size: 12.5px;
  font-weight: 600;
  border: 1px solid transparent;
}
.famstate--wait { background: var(--warn-pale); color: var(--warn); border-color: #E8D3A8; }
.famstate--ok   { background: var(--ok-pale);   color: var(--ok);   border-color: #B9DDC9; }
.famstate--stop { background: var(--stop-pale); color: var(--stop); border-color: #EDC3BB; }

/* --------------------------------------------------------------------------
   Forms

   16px on every field, without exception: anything smaller and iOS zooms the
   page on focus, which throws the layout sideways and is very hard to
   recover from on a phone held in one hand.
   -------------------------------------------------------------------------- */

.famform { margin: 0; }

.famfield { margin-bottom: var(--s4); }

.famfield label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--slate);
  margin-bottom: var(--s1);
}

.famfield input[type=text],
.famfield input[type=email],
.famfield input[type=tel],
.famfield input[type=password],
.famfield input[type=date],
.famfield select,
.famfield textarea {
  width: 100%;
  box-sizing: border-box;
  min-height: 48px;
  padding: var(--s2) var(--s3);
  font-family: var(--font-ui);
  font-size: 16px;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
}

.famfield input:focus,
.famfield select:focus,
.famfield textarea:focus {
  outline: 2px solid var(--info);
  outline-offset: 1px;
  background: var(--paper);
}

.famfield input.is-data { font-family: var(--font-data); letter-spacing: .06em; }

.famfield__note { margin: var(--s1) 0 0; font-size: 13px; color: var(--slate-pale); }
.famfield__error { margin: var(--s1) 0 0; font-size: 13px; color: var(--stop); font-weight: 500; }

.fambtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
  padding: 0 var(--s4);
  background: var(--ink);
  color: #fff;
  border: 1px solid var(--ink);
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.fambtn:hover,
.fambtn:focus,
a.fambtn:hover,
a.fambtn:visited {
  background: var(--ink-deep);
  border-color: var(--ink-deep);
  color: #fff;
  text-decoration: none;
}
a.fambtn, a.fambtn:link { color: #fff; text-decoration: none; }
.fambtn:focus-visible { outline: 2px solid var(--rubric); outline-offset: 2px; }

/* One accent to a screen. Everything that is not the single main action is
   quiet. */
.fambtn--quiet {
  background: transparent;
  color: var(--slate);
  border-color: var(--rule);
}
.fambtn--quiet:hover { background: var(--field); color: var(--ink); border-color: var(--slate-pale); }

.famlinks {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  margin-top: var(--s4);
  text-align: center;
}

.famlink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  color: var(--info);
  font-size: 14px;
  text-decoration: none;
}
.famlink:hover { text-decoration: underline; }

.famcheck {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  font-size: 15px;
  color: var(--slate);
  cursor: pointer;
}
.famcheck input { width: 20px; height: 20px; flex: none; }

/* --------------------------------------------------------------------------
   Phone and small tablet — the drawer

   820px is where the staff side hands the menu to a button, so this side does
   the same. One breakpoint across the whole application means a tablet held
   in portrait behaves identically whichever portal is open on it.
   -------------------------------------------------------------------------- */

@media (max-width: 820px) {
  .famhead__inner { flex-wrap: nowrap; gap: 10px; }
  .famhead__mark  { flex: 1; }
  .famhead__tools { order: 2; }

  /* The drawer slides over the bar, so the button that opens it has to ride
     above the drawer or there is no way back out except the dimmed area. */
  .famburger { display: grid; order: 3; position: relative; z-index: 220; }
  .famscrim:not([hidden]) { display: block; }

  /* No room for a second control beside the envelope, the language button
     and the bars. */
  .famout { display: none; }
  .famhead__inner { gap: var(--s2); }
  .fambell { padding: 0 var(--s1); }
}

/* Four controls and a name do not fit 320px. The name of the parish is the
   thing a parent already knows, so it is the thing that goes. */
@media (max-width: 400px) {
  .famhead__parish { display: none; }
  .famhead__name { font-size: 16px; }
  .famlang__btn { min-width: 0; padding: 0 var(--s2); font-size: 12px; }
}

@media (min-width: 600px) and (max-width: 820px) {
  .famfacts { grid-template-columns: 1fr 1fr; }
  .fambtn { width: auto; min-width: 220px; }
  .famlinks { flex-direction: row; justify-content: center; gap: var(--s5); }
}

/* --------------------------------------------------------------------------
   Computer

   Above 820px the menu is simply the menu, in the bar, beside the parish
   name — exactly where the staff side puts it. Same ink, same pale blue
   labels, same lit pill on the page you are reading. No second strip, no
   separate surface: one bar carries the whole navigation.

   Four sections, the same count the staff bar carries, so the row sits on one
   line. Where each section leads is the business of the column on the left.
   -------------------------------------------------------------------------- */

@media (min-width: 821px) {
  body.fam { font-size: var(--t-body); }

  .famburger { display: none; }
  .famscrim  { display: none !important; }

  .famhead__inner { padding: var(--s3) var(--s4); }
  .famhead__mark  { flex: none; }

  .famdrawer {
    position: static;
    transform: none;
    width: auto;
    flex: 1;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--s1);
    background: none;
    border-left: 0;
    box-shadow: none;
    padding: 0;
    margin: 0 0 0 var(--s4);
    overflow: visible;
  }

  /* The name sits behind the sign-out button on a wide screen. */
  .famdrawer__top { display: none; }

  .famdrawer__item {
    width: auto;
    min-height: 0;
    padding: var(--s2) var(--s3);
    font-size: var(--t-small);
    color: #C6CFE2;
    background: none;
    border-radius: var(--radius-sm);
    white-space: nowrap;
  }

  .famdrawer__item:hover { background: rgba(255, 255, 255, .10); color: #fff; }
  .famdrawer__item.is-on { background: rgba(255, 255, 255, .16); color: #fff; font-weight: 500; }

  /* Signing out is at the far end of the bar with the language button, so the
     menu reads as nine destinations and not ten. */
  .famdrawer__out { display: none; }

  .famgreet, .famcard__title, .famempty__title { font-size: var(--t-title); }
  .famfacts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fambtn { width: auto; min-width: 220px; }
  .famlinks { flex-direction: row; justify-content: center; gap: var(--s5); }
}

/* The account actions the bar carries on a wide screen. */
.famout { margin: 0; display: none; }

@media (min-width: 821px) {
  .famout { display: block; }
}

.famout__btn {
  padding: var(--s2) var(--s3);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--masthead-text);
  font-family: var(--font-ui);
  font-size: var(--t-small);
  cursor: pointer;
}
.famout__btn:hover { background: rgba(255, 255, 255, .10); color: #fff; }

/* --------------------------------------------------------------------------
   Motion and print
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .famdrawer, .famscrim { transition: none; }
}

@media print {
  .famhead__tools, .famdrawer, .famscrim { display: none !important; }
  body.fam { background: #fff; }
}

/* ==========================================================================
   Module 23 - registration
   ========================================================================== */

.famnarrow { max-width: 460px; margin: 0 auto; }

.famlede { margin: 0 0 var(--s4); color: var(--slate); font-size: 15px; line-height: 1.55; }

.famaside {
  text-align: center;
  margin: var(--s4) 0 0;
  font-size: 13px;
  color: var(--slate-pale);
  line-height: 1.5;
}

.famrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s3);
}

/* --------------------------------------------------------------------------
   How far along

   A form with no visible end is a form people abandon on step two.
   -------------------------------------------------------------------------- */

.famsteps { margin-bottom: var(--s4); }

.famsteps__label {
  margin: 0 0 var(--s1);
  font-size: 12.5px;
  color: var(--slate-pale);
  font-variant-numeric: tabular-nums;
}

.famsteps__track {
  height: 3px;
  background: var(--rule-soft);
  border-radius: 2px;
  overflow: hidden;
}

.famsteps__track span {
  display: block;
  height: 3px;
  background: var(--ink);
  border-radius: 2px;
  transition: width .3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .famsteps__track span { transition: none; }
}

/* --------------------------------------------------------------------------
   The two fields that carry a code

   Wide letter spacing so a parent can check what they typed against the paper
   character by character, which is exactly what people do.
   -------------------------------------------------------------------------- */

.famfield input.is-code {
  letter-spacing: .18em;
  text-transform: uppercase;
  font-size: 17px;
}

.famfield input.is-otp {
  font-family: var(--font-data);
  font-size: 22px;
  letter-spacing: .32em;
  text-align: center;
  min-height: 56px;
  padding-left: .32em;              /* the trailing gap, centred back */
}

.famlink--plain {
  background: none;
  border: 0;
  padding: 0;
  min-height: 0;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--info);
  cursor: pointer;
  text-decoration: none;
}
.famlink--plain:hover { text-decoration: underline; }

.famchild__meta { margin: 4px 0 0; font-size: 13px; color: var(--slate); }

.famchild__ask {
  margin: var(--s4) 0 var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-soft);
}

/* ==========================================================================
   Module 24 - consents
   ========================================================================== */

.famstate--info { background: var(--info-pale); color: var(--info); border-color: #C3D0EA; }
.famstate--gold { background: var(--rubric-pale); color: var(--rubric); border-color: #DCC79A; }

/* The draft mark. On the parent's screen, not in a footer: nobody should sign
   believing a text was reviewed when it was not. */
.famdraft {
  background: var(--field);
  border-left: 3px solid var(--slate-pale);
  padding: var(--s3);
  margin: 0 0 var(--s4);
  font-size: 13px;
  color: var(--slate);
  line-height: 1.5;
}

/* Consent wording is the one place in this portal where the text is long on
   purpose. Measure and leading matter more here than anywhere else. */
.famprose {
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink);
  max-width: 62ch;
  margin: 0 0 var(--s5);
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--rule-soft);
}

.famansw {
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule-soft);
}
.famansw:first-of-type { border-top: 0; }

.famansw__who {
  margin: 0 0 var(--s2);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.famansw__who .famdata { color: var(--slate-pale); font-weight: 400; margin-left: 4px; }

/* Two boxes, not two bare radios. On a phone the whole box is the target. */
.famchoice { display: flex; flex-direction: column; gap: var(--s2); }

.famchoice__opt {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-height: 48px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: 15px;
  color: var(--slate);
  cursor: pointer;
}
.famchoice__opt input { width: 20px; height: 20px; flex: none; accent-color: var(--ink); }
.famchoice__opt:has(input:checked) {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  color: var(--ink);
  font-weight: 500;
}

.famsum {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  padding: 6px 0;
  font-size: 14px;
  color: var(--slate);
}

.famsum__ans { font-weight: 600; flex: none; }
.famsum__ans--granted  { color: var(--ok); }
.famsum__ans--declined { color: var(--stop); }
.famsum__ans--unknown  { color: var(--slate-pale); }

.famversions { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--rule-soft); }
.famhash { word-break: break-all; }

.famwithdraw { margin: 0 0 var(--s2); }

.famnote {
  margin: var(--s3) 0 0;
  padding: var(--s3);
  border-radius: var(--radius-sm);
  font-size: 13px;
  line-height: 1.5;
}
.famnote--ok   { background: var(--ok-pale);   color: var(--ok);   border: 1px solid #B9DDC9; }
.famnote--wait { background: var(--warn-pale); color: var(--warn); border: 1px solid #E8D3A8; }

/* The signature pad. Wide and short, like the line on a paper form. */
.fampad {
  display: block;
  width: 100%;
  height: 180px;
  background: var(--field);
  border: 1px dashed var(--rule);
  border-radius: var(--radius-sm);
  touch-action: none;          /* or dragging a finger scrolls the page */
  cursor: crosshair;
}

/* ==========================================================================
   Module 25 - My Family
   ========================================================================== */

.famsubhead {
  margin: var(--s4) 0 var(--s1);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
}

.famhr { border: 0; border-top: 1px solid var(--rule-soft); margin: var(--s5) 0 0; }

.famverified {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  background: var(--ok-pale);
  color: var(--ok);
  border: 1px solid #B9DDC9;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
}

/* A contact row. The number on the left is the order somebody works down in
   an emergency, so it is set in the data face and never hidden. */
.famcontact {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule-soft);
}

.famcontact__n {
  flex: none;
  width: 22px;
  font-size: 14px;
  font-weight: 600;
  color: var(--rubric);
}

.famcontact__who { flex: 1; min-width: 0; }
.famcontact__who p { margin: 0; font-size: 15px; color: var(--ink); }
.famcontact__who span { font-size: 13px; color: var(--slate-pale); }

.famcontact__acts { display: flex; gap: 4px; flex: none; }
.famcontact__acts form { margin: 0; }

.famicon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  color: var(--slate);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.famicon:hover { background: var(--field); color: var(--ink); }
.famicon--stop:hover { background: var(--stop-pale); color: var(--stop); border-color: #EDC3BB; }

/* Collapsed by default. The common case is reading what is already there;
   adding is the exception, and an open form on every card is noise. */
.famadd { margin-top: var(--s3); }

.famadd > summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  color: var(--info);
  font-size: 14px;
  cursor: pointer;
  list-style: none;
}
.famadd > summary::-webkit-details-marker { display: none; }
.famadd > summary::before { content: '+'; margin-right: 6px; font-size: 16px; }
.famadd[open] > summary::before { content: '–'; }
.famadd > summary:hover { text-decoration: underline; }

.famadd .famform {
  padding: var(--s3) 0 0;
  border-top: 1px solid var(--rule-soft);
  margin-top: var(--s2);
}

.famfield textarea {
  resize: vertical;
  min-height: 60px;
  line-height: 1.5;
}

/* ==========================================================================
   Module 26 - the public legal pages
   ========================================================================== */

/* Long prose, read once, carefully. Measure and leading matter more here than
   anywhere else in the portal. */
.famlegal {
  max-width: 68ch;
  margin: 0 auto;
  padding-bottom: var(--s7);
}

.famlegal__title {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  line-height: 1.15;
  margin: var(--s1) 0 var(--s2);
  color: var(--ink);
}

.famlegal__meta {
  margin: 0 0 var(--s5);
  font-size: 13px;
  color: var(--slate-pale);
}

.famlegal h2 {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  color: var(--ink);
  margin: var(--s6) 0 var(--s2);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-soft);
}

.famlegal h3 {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  margin: var(--s4) 0 var(--s1);
}

.famlegal p  { margin: 0 0 var(--s3); font-size: 15px; line-height: 1.7; color: var(--ink); }
.famlegal ul { margin: 0 0 var(--s3); padding-left: var(--s5); }
.famlegal li { margin-bottom: var(--s2); font-size: 15px; line-height: 1.65; }
.famlegal a  { color: var(--info); }

.famlegal__foot { text-align: center; margin-top: var(--s5); }

.famlegal__copy {
  margin-top: var(--s5);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-soft);
  font-size: 13px;
  color: var(--slate-pale);
  line-height: 1.6;
}

@media (min-width: 821px) {
  .famlegal__title { font-size: var(--t-display); }
}

/* --------------------------------------------------------------------------
   Footer

   On every screen, signed in or not. A parent deciding whether to trust the
   slip in their hand should never have to hunt for the privacy notice.
   -------------------------------------------------------------------------- */

.famfoot {
  border-top: 1px solid var(--rule);
  margin-top: var(--s7);
  padding: var(--s5) var(--s4) var(--s6);
  background: var(--paper);
}

.famfoot__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  text-align: center;
}

.famfoot__links {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s2) var(--s5);
  margin-bottom: var(--s3);
}

.famfoot__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--slate);
  font-size: 14px;
  text-decoration: none;
}
.famfoot__links a:hover { color: var(--ink); text-decoration: underline; }

.famfoot__rights {
  margin: 0;
  font-size: 12.5px;
  color: var(--slate-pale);
  line-height: 1.6;
  max-width: 60ch;
  margin: 0 auto;
}

@media print { .famfoot { display: none; } }

/* ==========================================================================
   Module 29 - who is signed in, in the bar
   ========================================================================== */

/* Hidden on a phone, where the drawer already says it and the bar has no room
   left after the envelope, the language button and the menu. */
.famwho { display: none; }

@media (min-width: 821px) {
  .famwho {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    text-align: right;
    padding-right: var(--s2);
    margin-left: var(--s3);
  }

  .famwho__name {
    font-size: 13.5px;
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 22ch;
  }

  .famwho__role {
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #8FA0C4;
    font-weight: 600;
  }
}

/* ==========================================================================
   Module 30 - the parish name is a link
   ========================================================================== */

/* A link, but not one that looks like a link until a pointer finds it. A bar
   is not a place for underlines. */
.famhead__mark {
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius-sm);
  padding: 2px 6px;
  margin-left: -6px;
}

.famhead__mark:hover { background: rgba(255, 255, 255, .10); }
.famhead__mark:focus-visible { outline: 2px solid var(--masthead-gold); outline-offset: 2px; }

/* In the drawer it sits above the hairline with Sign Out, not among the nine
   destinations - it leaves the portal rather than moving inside it. */
.famdrawer__item--out { color: #8FA0C4; text-decoration: none; }

/* ==========================================================================
   Module 31 - Home in the menu, and a front page that notices you
   ========================================================================== */

/* The parish name is a name again. Whatever a previous rule made of it, this
   puts it back. */
.famhead__mark,
.famhead__mark:hover {
  text-decoration: none;
  background: none;
  color: inherit;
  padding: 0;
  margin-left: 0;
}

/* Home leaves the portal, so it is set apart from the sections that stay
   inside it: an icon, and a rule between. */
.famdrawer__item--away { display: flex; align-items: center; gap: 8px; }

@media (min-width: 821px) {
  .famdrawer__item--away {
    padding-right: 14px;
    margin-right: 6px;
    border-right: 1px solid rgba(255, 255, 255, .16);
  }
}

@media (max-width: 820px) {
  .famdrawer__item--away {
    margin-bottom: var(--s2);
    padding-bottom: var(--s3);
    border-bottom: 1px solid rgba(255, 255, 255, .14);
    border-radius: 0;
  }
}

/* --------------------------------------------------------------------------
   The front page when somebody is already signed in

   One card instead of two doors. Offering to sign in to a person who is
   signed in is the page not paying attention.
   -------------------------------------------------------------------------- */

.homeback {
  max-width: 420px;
  margin: 0 auto;
  background: var(--ink);
  border-radius: var(--radius);
  padding: var(--s5);
  text-align: left;
  box-shadow: var(--shadow-lift);
}

.homeback .famrubric { color: var(--masthead-gold); }

.homeback__name {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  color: #fff;
  margin: var(--s1) 0 var(--s4);
  line-height: 1.2;
}

.homeback__btn {
  width: 100%;
  background: #fff;
  color: var(--ink);
  border-color: #fff;
}
.homeback__btn:hover { background: var(--rule-soft); border-color: var(--rule-soft); }

.homeback form { margin: var(--s3) 0 0; text-align: center; }

.homeback__out {
  background: none;
  border: 0;
  min-height: 44px;
  padding: 0 var(--s3);
  color: var(--masthead-gold);
  font-family: var(--font-ui);
  font-size: 13px;
  cursor: pointer;
}
.homeback__out:hover { text-decoration: underline; }

/* ==========================================================================
   Module 36 - the unsigned consent strip
   ========================================================================== */

/* Amber, not red. Nothing has gone wrong - something is simply not finished,
   and red is reserved for a child the parish cannot reach or a permission
   that was refused. */
.famtodo {
  display: flex;
  align-items: center;
  gap: var(--s3);
  max-width: var(--max-width);
  margin: var(--s4) auto 0;
  padding: var(--s3) var(--s4);
  background: var(--warn-pale);
  border: 1px solid #E8D3A8;
  border-radius: var(--radius);
  color: var(--warn);
  text-decoration: none;
  line-height: 1.5;
  font-size: 14px;
}

.famtodo:hover { background: #F7E6C6; }

.famtodo strong { display: block; color: var(--ink); font-size: 15px; }

.famtodo__mark {
  flex: none;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--warn);
  color: #fff;
  font-weight: 700;
  font-size: 15px;
  line-height: 1;
}

.famtodo__go {
  flex: none;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: underline;
}

/* On a phone the call to action drops under the words rather than squeezing
   them into a column two syllables wide. */
@media (max-width: 560px) {
  .famtodo { flex-wrap: wrap; margin: var(--s3) var(--s3) 0; }
  .famtodo__go { width: 100%; text-align: right; }
}

@media print { .famtodo { display: none; } }

/* ==========================================================================
   The consent card, on a wide screen
   ========================================================================== */

/* The prose is held to 62 characters on purpose: a line much longer than that
   and the eye loses its place coming back to the start of the next one. That
   is right, and it stays.
   
   What was wrong is that the card around it stretched to whatever the screen
   allowed, leaving a narrow column of words adrift in a wide empty box. The
   card now follows the text instead of the window. */
.famcard:has(.famprose) {
  max-width: 68ch;
}

/* And the type grows with the screen rather than jumping at a breakpoint:
   15px on a telephone, up to about 17px on a desktop, sliding between. Long
   reading is easier a shade larger when there is room for it. */
.famprose {
  font-size: clamp(15px, 0.9rem + 0.35vw, 17px);
}

.famprose h3,
.famprose h4 {
  font-size: clamp(15px, 0.92rem + 0.35vw, 17.5px);
  margin: var(--s4) 0 var(--s2);
  color: var(--ink);
}

/* Paragraphs need air between them or the headings stop dividing anything. */
.famprose p { margin: 0 0 var(--s3); }
.famprose p:last-child { margin-bottom: 0; }

.famprose ul,
.famprose ol {
  margin: 0 0 var(--s3);
  padding-left: var(--s5);
}

.famprose li { margin-bottom: var(--s1); }

/* Turned sideways on a narrow screen, the links kept wrapping: "Permisos y
   documentos" broke across two lines inside its own tab, so the row read as
   six half-labels instead of three items. They stay on one line now and the
   row scrolls sideways when there are more than fit. */
@media (max-width: 860px) {
  .famsidenav > a,
  .famsidenav__link {
    white-space: nowrap;
    flex: 0 0 auto;
  }

  /* The heading above the list has no place in a horizontal row. */
  .famsidenav__title { display: none; }
}

/* --------------------------------------------------------------------------
   Registration - the email step and the password eye
   Field widths follow their content. A six digit box the width of the card
   makes the eye travel over empty space to find where it ends.
   -------------------------------------------------------------------------- */
.famfield--wide  input { max-width: 340px; width: 100%; }
.famfield--short input { max-width: 150px; }
.fambtn--auto { display: inline-flex; width: auto; padding-left: var(--s5); padding-right: var(--s5); }

.regcode {
  margin-top: var(--s5);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}
.regcode.is-off { opacity: .45; }
.regcode.is-off .regcode__input {
  border-style: dashed;
  background: var(--fill-muted, #eef1f7);
}
.regcode__sent {
  background: var(--bg-ok, #eaf5ee);
  border-radius: 8px;
  padding: var(--s3);
  margin-bottom: var(--s4);
  font-size: 14px;
  line-height: 1.55;
}
.regcode__row { display: flex; gap: 8px; align-items: stretch; }
.regcode__input { letter-spacing: .3em; }
.regcode__again {
  width: 44px;
  flex: none;
  border: 1px solid var(--rule-strong, #b9c2d4);
  border-radius: 8px;
  background: var(--paper, #fff);
  color: var(--ink-link, #2f5fd0);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.regcode__again:disabled { opacity: .4; cursor: default; }

.regpass { position: relative; max-width: 340px; }
.regpass input { width: 100%; padding-right: 44px; }
.regpass__eye {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border: 0;
  background: none;
  color: var(--ink-soft, #6b7488);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.regpass__eye.is-open { color: var(--ink-link, #2f5fd0); }

@media (max-width: 560px) {
  .famfield--wide input,
  .regpass { max-width: none; }
  .fambtn--auto { display: block; width: 100%; }
}

/* --------------------------------------------------------------------------
   Standard card width
   One width for every screen in the family portal, so a parent moving from
   one step to the next sees the card stay still instead of growing and
   shrinking with whatever happens to be inside it.

   Fixed, not a maximum: without a floor the card collapses onto short
   content, which is what made the email step narrower than the one after it.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  .famnarrow,
  .famcard:has(.famprose),
  .famshell--split .famcard {
    width: 700px;
    max-width: 700px;
    margin-left: auto;
    margin-right: auto;
  }
}

@media (min-width: 561px) and (max-width: 820px) {
  .famnarrow,
  .famcard:has(.famprose) {
    width: 100%;
    max-width: 700px;
    margin-left: auto;
    margin-right: auto;
  }
}

@media (max-width: 560px) {
  .famnarrow,
  .famcard:has(.famprose) {
    width: auto;
    max-width: none;
  }
}
/* Edge and Chrome add their own reveal control. Two eyes in one field
   is one too many, and theirs sits under ours. */
.regpass input::-ms-reveal,
.regpass input::-ms-clear { display: none; }
.regpass input::-webkit-credentials-auto-fill-button,
.regpass input::-webkit-strong-password-auto-fill-button {
  visibility: hidden;
  pointer-events: none;
  position: absolute;
  right: 0;
}

.famreq { color: var(--ink-warn, #b4442e); font-weight: 600; }

/* --------------------------------------------------------------------------
   The bar on a wide screen, matched to the staff one

   The staff menu never wraps: its items push against each other and the row
   holds. This one was allowed to wrap, so the last item dropped to a second
   line and left the bar looking broken. Same rule here, and the user block
   trimmed to the size the staff bar gives it, since that block was taking the
   width the menu needed.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  .famhead__inner { flex-wrap: nowrap; gap: var(--s3); }

  .famdrawer {
    flex-wrap: nowrap;
    justify-content: flex-start;
    margin-left: var(--s5);
    flex: 1 1 auto;
    min-width: 0;
  }

  .famdrawer__item { padding: var(--s2) var(--s3); }

  .famhead__tools { margin-left: 0; flex: none; }

  /* The staff bar says ADMIN in a line you read only if you look for it.
     This said PARENT PORTAL twice the size, and the menu paid for it. */
  .famwho { line-height: 1.15; }
  .famwho__name { font-size: var(--t-small); white-space: nowrap; }
  .famwho__role { font-size: 9.5px; letter-spacing: .12em; }
}

/* Between the fold and a comfortable desktop the menu is the first thing to
   give: the parish name shortens before any destination is lost. */
@media (min-width: 821px) and (max-width: 1080px) {
  .famhead__parish { display: none; }
  .famhead__name   { font-size: 16px; }
  .famdrawer__item { padding: var(--s2) var(--s2); font-size: 13px; }
  .famwho          { display: none; }
}

/* --------------------------------------------------------------------------
   The bar, second pass

   nowrap stopped the second row but let the menu run under the envelope: it
   was allowed to grow and never to shrink. Now it gives way instead, and the
   tools keep a lane of their own that nothing else can enter.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  .famhead__inner { gap: var(--s2); }

  .famdrawer {
    flex: 0 1 auto;
    min-width: 0;
    margin-left: var(--s4);
    margin-right: var(--s3);
    overflow: hidden;
  }

  .famdrawer__item { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

  .famhead__tools {
    flex: none;
    margin-left: auto;
    padding-left: var(--s3);
  }

  .fambell { flex: none; }
}

/* Narrower side margins: the parish name and the sign-out button sat a long
   way from the edges on a wide screen, which made the bar look emptier than
   the page below it. */
@media (min-width: 821px) {
  .famhead__inner,
  .famshell,
  .famshell--split,
  .fampage,
  .famfoot__inner,
  .wayfind__inner { padding-left: var(--s3); padding-right: var(--s3); }
}

/* --------------------------------------------------------------------------
   The name, and what opens under it

   Same shape as the staff bar's account menu, same numbers, so the two
   portals behave alike for somebody who uses both.
   -------------------------------------------------------------------------- */
.famacct { position: relative; display: none; }

@media (min-width: 821px) {
  .famacct { display: block; }
}

.famacct__btn {
  display: flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  color: #C6CFE2;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  cursor: pointer;
}
.famacct__btn:hover { background: rgba(255, 255, 255, .10); color: #fff; }
.famacct__btn[aria-expanded="true"] { background: rgba(255, 255, 255, .16); color: #fff; }
.famacct__btn svg { transition: transform .16s ease; flex: none; }
.famacct__btn[aria-expanded="true"] svg { transform: rotate(180deg); }

.famacct__text { display: flex; flex-direction: column; line-height: 1.25; text-align: right; }
.famacct__name { font-size: 13.5px; font-weight: 600; color: #fff; white-space: nowrap; }
.famacct__role { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: #8FA0C4; }

.famacct__menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 220;
  min-width: 184px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  overflow: hidden;
  padding: 4px;
}
.famacct__menu[hidden] { display: none !important; }

.famacct__item {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 14px;
  color: var(--ink);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
}
.famacct__item:hover { background: var(--field); }
/* In the drawer on a phone, behind the name on a computer. */
@media (min-width: 821px) {
  .famdrawer__item--phone { display: none; }
}

/* --------------------------------------------------------------------------
   The name at the top of the drawer, now a button

   Same two destinations as the computer, in the same place: under the name.
   -------------------------------------------------------------------------- */
.famdrawer__whobtn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  font: inherit;
  color: #fff;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  cursor: pointer;
  text-align: left;
}
.famdrawer__whobtn:hover { background: rgba(255, 255, 255, .10); }
.famdrawer__whobtn svg { transition: transform .16s ease; flex: none; color: #8FA0C4; }
.famdrawer__whobtn[aria-expanded="true"] svg { transform: rotate(180deg); }
.famdrawer__whotext { display: flex; flex-direction: column; min-width: 0; }
.famdrawer__whomenu[hidden] { display: none !important; }
.famdrawer__whomenu { padding: 4px 0 6px; }
.famdrawer__item--sub { font-size: 15px; padding-left: 22px; opacity: .92; }

/* --------------------------------------------------------------------------
   The name's menu floats over the list

   Pushing the destinations down made the whole drawer jump on every open.
   Now it sits above them, the way the computer one does, on its own paper.
   -------------------------------------------------------------------------- */
.famdrawer__top { position: relative; }

.famdrawer__whomenu {
  position: absolute;
  top: calc(100% + 2px);
  left: 8px;
  right: 8px;
  z-index: 30;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: 4px;
}

.famdrawer__whomenu .famdrawer__item--sub {
  color: var(--ink);
  font-size: 15px;
  padding: 10px 12px;
  min-height: 0;
  border-radius: var(--radius-sm);
  opacity: 1;
}
.famdrawer__whomenu .famdrawer__item--sub:hover { background: var(--field); color: var(--ink); }

/* --------------------------------------------------------------------------
   The name's menu, in the drawer's own colours

   Paper on a dark drawer read as a different surface altogether. It keeps the
   drawer's ink instead, and what sits under it dims so the two do not blur
   into one list.
   -------------------------------------------------------------------------- */
.famdrawer__whomenu {
  background: var(--ink);
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
}

.famdrawer__whomenu .famdrawer__item--sub,
.famdrawer__whomenu .famdrawer__item--sub:hover {
  color: #fff;
}
.famdrawer__whomenu .famdrawer__item--sub:hover { background: rgba(255, 255, 255, .12); }

/* Everything below the name goes quiet while the menu is open. */

/* --------------------------------------------------------------------------
   The name's menu, in the drawer's own colours

   Paper on a dark drawer read as a different surface altogether. It keeps the
   drawer's ink instead, and what sits under it dims so the two do not blur
   into one list.
   -------------------------------------------------------------------------- */
.famdrawer__whomenu {
  background: var(--ink);
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
}

.famdrawer__whomenu .famdrawer__item--sub,
.famdrawer__whomenu .famdrawer__item--sub:hover {
  color: #fff;
}
.famdrawer__whomenu .famdrawer__item--sub:hover { background: rgba(255, 255, 255, .12); }

/* Everything below the name goes quiet while the menu is open. */

/* --------------------------------------------------------------------------
   A curtain, not a fade

   Lowering each item's opacity made them translucent, so the list read
   through the menu sitting on top of it. A dark sheet over the drawer does
   the opposite: everything behind goes quiet, and the menu rises above it.
   -------------------------------------------------------------------------- */
.famdrawer.has-who-open::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(8, 14, 28, .72);
  backdrop-filter: blur(2px);
  z-index: 20;
}

.famdrawer__top { z-index: 25; }
.famdrawer__whomenu { z-index: 30; }

/* --------------------------------------------------------------------------
   The footer on a phone

   Nine stacked lines took most of a screen. What a parent needs when
   something goes wrong is the office: its address and telephone are already
   tappable links, so they stay and turn into two buttons. The postal address
   and the parish site go - nobody copies a street address off a footer on a
   telephone, and the site is a destination in the menu already.

   The full footer returns above 640px, where the width costs nothing.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .sitefoot__inner {
    display: block;
    text-align: center;
    padding-bottom: var(--s3);
  }

  /* The parish block keeps its name and drops the street. */
  .sitefoot__col:nth-child(2) .sitefoot__rubric,
  .sitefoot__col:nth-child(2) p:nth-of-type(2) { display: none; }

  /* The website column goes entirely: it is in the menu. */
  .sitefoot__col:nth-child(3) { display: none; }

  .sitefoot__col + .sitefoot__col { margin-top: var(--s3); }

  /* Two taps, side by side, at the size a thumb expects. */
  .sitefoot__col:first-child p {
    display: inline-block;
    margin: 4px 3px 0;
  }
  .sitefoot__col:first-child a {
    display: inline-block;
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 20px;
    padding: 8px 15px;
    text-decoration: none;
    font-size: 14px;
  }

  .sitefoot__bar { padding-top: var(--s3); }
  .sitefoot__links { gap: var(--s3); }
  .sitefoot__owner { font-size: 11px; }
}

/* Short labels on a phone, the full detail everywhere else. The address and
   the number still travel in the link itself, so the tap does the same thing. */
.sitefoot__short { display: none; }
.sitefoot__ico   { display: none; vertical-align: -3px; margin-right: 6px; }

@media (max-width: 640px) {
  .sitefoot__long  { display: none; }
  .sitefoot__short { display: inline; }
  .sitefoot__ico   { display: inline-block; }
  .sitefoot__col:first-child a { padding: 9px 18px; }
}
/* --------------------------------------------------------------------------
   Mis hijos: today, the tally, what is still owed
   -------------------------------------------------------------------------- */
.famtoday__line { display: flex; align-items: center; gap: 12px; margin: 6px 0 4px; }
.famtoday__mark {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; color: #fff;
}
.famtoday__mark--in   { background: var(--ok, #2f7d4f); }
.famtoday__mark--wait { background: var(--rule-strong, #b9c2d4); }
.famtoday__head { font-family: var(--font-display); font-size: 21px; margin: 0; line-height: 1.2; }
.famtoday__note { margin: 2px 0 0 38px; font-size: 14px; color: var(--slate); }

.famtally { border-top: 1px solid var(--rule-soft); margin-top: var(--s4); padding-top: var(--s4); }
.famtally__row + .famtally__row { margin-top: var(--s4); }
.famtally__top { display: flex; justify-content: space-between; align-items: baseline;
  font-size: 15px; margin-bottom: 6px; }
.famtally__note { margin: 5px 0 0; font-size: 13px; color: var(--slate); line-height: 1.5; }

.fambar { height: 6px; background: var(--field, #eef1f7); border-radius: 3px; overflow: hidden; }
.fambar span { display: block; height: 6px; border-radius: 3px; }
.fambar .is-ok    { background: var(--ok, #2f7d4f); }
.fambar .is-watch { background: var(--warn, #b98a2e); }

.famtodo2__row { display: flex; align-items: center; gap: var(--s3); padding: 8px 0; }
.famtodo2__row + .famtodo2__row { border-top: 1px solid var(--rule-soft); }
.famtodo2__text { flex: 1; font-size: 15px; }
.fambtn--small {
  display: inline-flex;
  width: auto;
  min-height: 38px;
  padding: 0 var(--s4);
  font-size: 14px;
  flex: none;
}

.famnotice { display: block; text-decoration: none; color: inherit; }
.famnotice__title { display: block; font-size: 15px; margin-bottom: 3px; }
.famnotice__when  { display: block; font-size: 13px; color: var(--slate); }

/* --------------------------------------------------------------------------
   Mis hijos, second pass

   The day card reads down one margin now, with the child's face on the right.
   The old tick sat in the text's way and pushed the second line in by itself.
   -------------------------------------------------------------------------- */
.famtoday { display: flex; align-items: center; gap: var(--s4); }
.famtoday__left { flex: 1; min-width: 0; }
.famtoday__note { margin: 3px 0 0; }          /* no indent: one left margin */
.famtoday__face {
  flex: none;
  width: 84px; height: 84px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--field);
  border: 1px solid var(--rule);
}

/* Four facts fit on a wide screen; the catechist was dropping to a line of
   its own with the room to spare beside it. */
@media (min-width: 640px) {
  .famfacts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); }
}
@media (max-width: 639px) {
  .famfacts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
  .famtoday__face { width: 64px; height: 64px; }
}
/* --------------------------------------------------------------------------
   Attendance: the record, one row to a session

   The line is the session's own timetable, drawn to scale: the door opening at
   the left, the end at the right, with the start and the end of the grace
   period marked between them. The arrows are where the child actually was.
   -------------------------------------------------------------------------- */
.famsums { display: flex; gap: var(--s6); flex-wrap: wrap; margin-top: var(--s2); }
.famsums__n { display: block; font-family: var(--font-display); font-size: 21px; line-height: 1.2; }
.famsums__t { display: block; font-size: 13px; color: var(--slate); }

.famtabs { display: flex; gap: var(--s1); margin: var(--s4) 0 var(--s3); }
.famtabs__t {
  padding: 8px 18px; border-radius: var(--radius-sm);
  font-size: 15px; color: var(--slate); text-decoration: none;
}
.famtabs__t:hover { background: var(--field); color: var(--ink); }
.famtabs__t.is-on { background: var(--field); color: var(--ink); font-weight: 600; }

.famkey { display: flex; gap: var(--s5); flex-wrap: wrap; font-size: 12px;
  align-items: center;
  color: var(--slate); margin: 0 0 var(--s2); }
.famkey__i { margin-right: 5px; }
.famkey__i--ok   { color: var(--ok, #2f7d4f); }
.famkey__i--late { color: var(--warn, #b98a2e); }
.famkey__i--out  { color: var(--slate); }

.famlist { padding: 0; overflow: hidden; }
.famrow { display: flex; align-items: center; gap: var(--s4); padding: 13px var(--s4); }
.famrow + .famrow { border-top: 1px solid var(--rule-soft); }
.famrow__when { width: 190px; flex: none; }
.famrow__day { display: block; font-size: 15px; }
.famrow__times { display: block; font-size: 13px; color: var(--slate); }
.famrow__state { width: 92px; flex: none; text-align: right; font-size: 13px; color: var(--ok, #2f7d4f); }
.famrow__state--late, .famrow__state.is-early { color: var(--warn, #b98a2e); }
.famrow__state--absent { color: var(--slate-pale); }

.famline { position: relative; flex: 1; min-width: 0; height: 22px; }
.famline.is-off { opacity: .35; }
.famline__bar { position: absolute; top: 14px; left: 0; right: 0; height: 2px;
  background: var(--rule-strong, #b9c2d4); }
.famline__tick { position: absolute; top: 9px; width: 2px; height: 12px;
  background: var(--rule-strong, #b9c2d4); }
.famline__arrow { position: absolute; top: 0; font-size: 12px; line-height: 1;
  transform: translateX(-50%); }
.famline__arrow.is-ok   { color: var(--ok, #2f7d4f); }
.famline__arrow.is-late { color: var(--warn, #b98a2e); }
.famline__arrow.is-out  { color: var(--slate); }

.famaside--note { font-size: 13px; color: var(--slate); line-height: 1.6;
  background: var(--field); border-radius: var(--radius-sm);
  padding: var(--s3) var(--s4); margin-top: var(--s4); }

/* Stacked on a telephone: the line needs the whole width to stay readable. */
@media (max-width: 620px) {
  .famrow { flex-wrap: wrap; gap: var(--s2); }
  .famrow__when  { width: auto; flex: 1; }
  .famrow__state { width: auto; }
  .famline { flex: 0 0 100%; order: 3; }
}

/* --------------------------------------------------------------------------
   The session bar, in three stretches

   Thin outline, the stretches inside it, and the reading time set over each
   arrow rather than beside it, so a row stays readable at a glance.
   -------------------------------------------------------------------------- */
.fambar2 { position: relative; flex: 1; min-width: 0; height: 32px; }
.fambar2.is-off { opacity: .4; }

.fambar2__track {
  position: absolute; bottom: 0; left: 0; right: 0;
  height: 9px; display: flex; overflow: hidden;
  border: 1px solid var(--rule-strong, #b9c2d4);
  border-radius: 5px;
}
.fambar2__seg { display: block; height: 100%; }

/* Four bands, each named for what it means to a parent. Green is on
   time; the amber grace still counts as on time; red is late; and past
   the dark line the arrival no longer counts towards the term, which is
   a different thing from being late. */
.fambar2__seg--early { background: #97C459; }
.fambar2__seg--grace { background: #FAC775; }
.fambar2__seg--late  { background: #F09595; }
.fambar2__seg--gone  { background: #791F1F; }

/* Blue arrives, amber leaves: the arrival lands on the pale end of the
   bar and the departure on the dark one, so neither disappears. */
.fambar2__a.is-in  { color: #378ADD; }
.fambar2__a.is-out { color: #EF9F27; }

.fambar2__pin { position: absolute; bottom: 9px; transform: translateX(-50%); text-align: center; }
.fambar2__t { display: block; font-size: 11px; line-height: 1.1; color: var(--ink); white-space: nowrap; }
.fambar2__a { display: block; font-size: 11px; line-height: 1; }
.fambar2__a.is-ok   { color: var(--ok, #2f7d4f); }
.fambar2__a.is-late { color: var(--warn, #b98a2e); }
.fambar2__a.is-out  { color: var(--slate); }

.famkey__c {
  display: inline-block; width: 12px; height: 9px; border-radius: 3px;
  border: 1px solid var(--rule-strong, #b9c2d4); margin-right: 6px; vertical-align: -1px;
}
.famkey__c--early { background: #97C459; }
.famkey__c--grace { background: #FAC775; }
.famkey__c--late  { background: #F09595; }
.famkey__c--gone  { background: #791F1F; }

@media (max-width: 620px) {
  .fambar2 { flex: 0 0 100%; order: 3; height: 34px; }
}

/* One block to a weekend: the unit the term actually counts. */
.famweek { padding: 0; overflow: hidden; }
.famweek__head {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: 12px var(--s4); border-bottom: 1px solid var(--rule-soft);
  background: var(--field);
}
.famweek__when  { font-size: 15px; font-weight: 600; }
.famweek__state { font-size: 13px; }
.famweek__state.is-met { color: var(--ok, #2f7d4f); }
.famweek__state.is-not { color: var(--slate); }
.famrow--inweek { padding-left: var(--s5); }
.famrow--inweek + .famrow--inweek { border-top: 1px solid var(--rule-soft); }

/* --------------------------------------------------------------------------
   The week

   Seven columns where there is room; below that the same markup slides under
   the finger. Dragging scrolls and a tap opens - which is what every list on
   a telephone already does, so nobody has to be taught.
   -------------------------------------------------------------------------- */
.famweeknav { display: flex; align-items: center; justify-content: space-between;
  margin: var(--s4) 0 var(--s3); gap: var(--s3); }
.famweeknav__range { font-family: var(--font-display); font-size: 17px; }
.famweeknav__go { font-size: 14px; color: var(--ink-link, #2f5fd0); text-decoration: none; }
.famweeknav__go.is-off { color: var(--slate-pale); }

.famcal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; align-items: start; }
.famcal__day {
  background: var(--paper); border: 1px solid var(--rule); border-radius: 10px;
  padding: 9px 7px; height: 168px; display: flex; flex-direction: column;
}
.famcal__day.is-empty { background: var(--field); }
.famcal__day.is-today { border-color: var(--ink-link, #2f5fd0); border-width: 2px; padding: 8px 6px; }
.famcal__dow { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--slate); }
.famcal__num { font-family: var(--font-display); font-size: 18px; line-height: 1.1; margin-bottom: 6px; }

/* Inside a day: as many as fit, the rest reached by dragging. */
.famcal__slots { flex: 1; min-height: 0; overflow-y: auto; display: flex;
  flex-direction: column; gap: 4px; -webkit-overflow-scrolling: touch; }

.famcal__ev { display: block; width: 100%; text-align: left; border: 0; cursor: pointer;
  border-radius: 6px; padding: 5px 6px; font: inherit; background: var(--field); }
.famcal__ev--class { background: var(--bg-accent, #e8eefb); }
.famcal__ev:hover { filter: brightness(.97); }
.famcal__ev.is-off { background: none; border: 1px dashed var(--rule-strong, #b9c2d4); }
.famcal__ev.is-off .famcal__time { text-decoration: line-through; }
.famcal__time { display: block; font-size: 11px; font-weight: 600; }
.famcal__what { display: block; font-size: 10.5px; color: var(--slate); }
.famcal__why  { display: block; font-size: 10px; color: var(--warn, #b98a2e); margin-top: 2px; }

.famsheet { position: fixed; inset: 0; z-index: 400; background: rgba(12, 20, 38, .5);
  display: flex; align-items: center; justify-content: center; padding: var(--s4); }
.famsheet[hidden] { display: none !important; }
.famsheet__box { background: var(--paper); border-radius: var(--radius);
  box-shadow: var(--shadow-lift); padding: var(--s5); max-width: 380px; width: 100%; }
.famsheet__head { display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--s3); margin-bottom: var(--s3); }
.famsheet__kind { font-size: 11px; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ink-link, #2f5fd0); }
.famsheet__title { font-family: var(--font-display); font-size: 19px; margin: 2px 0 0; }
.famsheet__x { border: 0; background: none; font-size: 22px; line-height: 1;
  color: var(--slate); cursor: pointer; }
.famsheet__facts { display: grid; grid-template-columns: auto 1fr; gap: 5px var(--s4);
  margin: 0 0 var(--s3); font-size: 14px; }
.famsheet__facts dt { color: var(--slate); }
.famsheet__facts dd { margin: 0; }
.famsheet__note { margin: 0; background: var(--field); border-radius: var(--radius-sm);
  padding: var(--s3); font-size: 13px; color: var(--slate); line-height: 1.6; }

@media (max-width: 760px) {
  .famcal { display: flex; overflow-x: auto; gap: 6px; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
  .famcal__day { flex: 0 0 45%; scroll-snap-align: start; height: 190px; }
}

/* --------------------------------------------------------------------------
   Width, by the same rule the staff side uses

   Lists and calendars take the room they need; forms and consent prose keep
   a reading measure, because a line of 180 characters loses the eye on the
   way back and a single field adrift in white space is worse, not better.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  body .famshell--wide { width: 100%; }

  .famshell.famshell--wide,
  .fampage.fampage--wide,
  body .famshell--wide,
  body .fampage--wide {
    /* width, not just max-width: a grid in a block container grows only
       to what its content asks for, so a ceiling alone changed nothing. */
    width: 100%;
    max-width: min(var(--max-wide, 1600px), 94vw) !important;
  }

  /* Inside a wide page the cards stop being pinned to 700: the 700 rule
     lives in a media query of its own and was outweighing this one. */
  .fampage--wide .famnarrow,
  body .fampage--wide .famnarrow {
    width: auto !important;
    max-width: none !important;
    margin-left: 0;
    margin-right: 0;
  }
}

/* --------------------------------------------------------------------------
   The bar and the footer follow the page

   A wide calendar under a bar still pinned to 1000px leaves the parish name
   floating in the middle of nothing. The staff side solves it the same way,
   with :has() on the shell.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  body:has(.famshell--wide) .famhead__inner,
  body:has(.famshell--wide) .sitefoot__inner,
  body:has(.famshell--wide) .sitefoot__bar,
  body:has(.famshell--wide) .wayfind__inner {
    max-width: min(var(--max-wide, 1600px), 94vw);
  }
}
/* A hint that the day holds more than fits: a soft fade at the foot of the
   list, which is how a strip of anything says "there is more below". */
.famcal__slots { scrollbar-width: thin; }
.famcal__day:has(.famcal__slots) { position: relative; }

/* --------------------------------------------------------------------------
   Everything on a wide page shares one left edge

   Freeing famnarrow of its 700px let the cards grow, but the tabs, the key and
   the closing note kept their own widths, so nothing lined up with anything.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  .fampage--wide .famnarrow > * { width: 100%; box-sizing: border-box; }
  .fampage--wide .famaside--note { max-width: none; }
  .fampage--wide .famtabs,
  .fampage--wide .famkey { width: 100%; }
}

/* --------------------------------------------------------------------------
   Cards on a wide page

   The 700px measure was set for consent prose, where a long line loses the eye
   on its way back. A list of sessions is not prose: it has columns, and pinning
   it to 700 left it adrift while the tabs above it ran the full width.
   -------------------------------------------------------------------------- */
@media (min-width: 821px) {
  .fampage--wide .famcard,
  .fampage--wide .famshell--split .famcard,
  body .fampage--wide .famcard { max-width: none; width: 100%; }

  /* Prose keeps its measure wherever it is. */
  .fampage--wide .famcard:has(.famprose) { max-width: 68ch; }
}

/* --------------------------------------------------------------------------
   The frame, and the photograph moving under it

   Square, because the square is what gets cut and sent: a supervisor sees the
   result rather than an approximation of it. The circle inside marks where the
   face belongs and stops there - BioTime wants some background around a face,
   so the whole square travels, not the circle.
   -------------------------------------------------------------------------- */
.faceframe {
  position: relative;
  width: 200px;
  aspect-ratio: 1;
  border-radius: 10px;
  overflow: hidden;
  background: #2b3550;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.faceframe.is-dragging { cursor: grabbing; }

.faceframe img {
  position: absolute;
  max-width: none;
  pointer-events: none;
  display: block;
}

/* The ring is drawn over everything and takes no clicks. */
.faceframe__ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 62%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .95);
  box-shadow: 0 0 0 999px rgba(10, 16, 30, .45);
  pointer-events: none;
}

.facezoom { display: flex; align-items: center; gap: 10px; width: 200px; margin-top: 10px; }
.facezoom input[type="range"] { flex: 1; }
.facezoom span { font-size: 14px; color: var(--slate); }

.facehint { width: 200px; margin: 6px 0 0; font-size: 12px; color: var(--slate); line-height: 1.5; }

@media (max-width: 560px) {
  .faceframe, .facezoom, .facehint { width: 100%; max-width: 300px; }
}

/* The head keeps its rule: it was carried by famcard__head, which this row
   replaced. And the row is a row - the name sits beside the face, not under
   the whole of it. */
.famkidhead {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-bottom: var(--s4);
  margin-bottom: var(--s4);
  border-bottom: 1px solid var(--rule-soft);
}
.famkidhead__who { flex: 1; min-width: 0; }
.famkidhead__who .famcard__title { margin: 2px 0 0; }

/* The camera, while it is looking. */
.famqr { margin: var(--s3) 0; text-align: center; }
.famqr video { width: 100%; max-width: 320px; border-radius: 10px; background: var(--ink); display: block; margin: 0 auto var(--s2); }
.famqr__hint { font-size: 14px; color: var(--slate); margin: 0 0 var(--s3); }
.famqr__open { margin: var(--s4) 0 var(--s2); }

/* The quiet button, when it is a link. The dark one was fixed earlier; this
   one still lost its text, because a link's own colour was winning over the
   button's and landing white on white. */
a.fambtn--quiet,
a.fambtn--quiet:link,
a.fambtn--quiet:visited {
  color: var(--slate);
  text-decoration: none;
}
a.fambtn--quiet:hover,
a.fambtn--quiet:focus {
  color: var(--ink);
  background: var(--field);
  border-color: var(--slate-pale);
  text-decoration: none;
}

/* On a telephone the auto button goes full width, and the rule that did it
   used display:block - which drops the flex that was centring the text. */
@media (max-width: 560px) {
  .fambtn--auto {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: center;
  }
}

/* The camera fills the width and sits above its own button. */
@media (max-width: 560px) {
  .famqr video { max-width: none; width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }
}

/* The camera keeps within the screen: a picture taller than the telephone
   means scrolling to see what the lens is pointing at. */
@media (max-width: 560px) {
  .famqr video { aspect-ratio: auto; height: 58vh; max-height: 460px; object-fit: cover; }
}

/* --------------------------------------------------------------------------
   The envelope

   What was read stays: a photograph approved last week is a thing a parent
   might want to look at again. It simply stops asking for attention.
   -------------------------------------------------------------------------- */
.fammsg { padding: var(--s4); border-bottom: 1px solid var(--rule-soft); }
.fammsg:last-child { border-bottom: 0; }
.fammsg.is-new { background: var(--field); border-left: 3px solid var(--ink-link, #2f5fd0); }
.fammsg__head { display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--s3); flex-wrap: wrap; }
.fammsg__title { font-weight: 600; font-size: 15px; }
.fammsg__when { font-size: 13px; color: var(--slate-pale); white-space: nowrap; }
.fammsg__body { margin: 5px 0 0; font-size: 14px; color: var(--slate); line-height: 1.6; }
.fammsg__go { display: inline-block; margin-top: var(--s2); font-size: 14px; }

/* The gap under a message came from famlist expecting rows of its own. */
.famlist .fammsg { padding-bottom: var(--s3); }
.fammsg__go { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   The envelope, sealed and opened

   A closed envelope for what has not been read, an open one for what has. The
   picture says it without a word, in either language, and a parent who has
   never used a portal knows what it means.
   -------------------------------------------------------------------------- */
.fammsg {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  padding: var(--s4);
  border-bottom: 1px solid var(--rule-soft);
}
.fammsg:last-child { border-bottom: 0; }
.fammsg:hover { background: var(--field); }

.fammsg__icon { flex: none; color: var(--slate-pale); margin-top: 1px; }
.fammsg.is-new { background: var(--field); border-left: 3px solid var(--ink-link, #2f5fd0); }
.fammsg.is-new .fammsg__icon { color: var(--ink-link, #2f5fd0); }

.fammsg__text { flex: 1; min-width: 0; }
.fammsg__title { display: block; font-size: 15px; }
.fammsg.is-new .fammsg__title { font-weight: 700; }

/* One line of the message, for something already read. */
.fammsg__peek {
  display: block;
  margin-top: 2px;
  font-size: 13.5px;
  color: var(--slate);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fammsg__when { flex: none; font-size: 13px; color: var(--slate-pale); white-space: nowrap; }

.famtabs__n {
  display: inline-block;
  margin-left: 6px;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--ink-link, #2f5fd0);
  color: #fff;
  font-size: 12px;
  line-height: 18px;
  text-align: center;
}

.famsheet__when { margin: 0 0 var(--s3); font-size: 13px; color: var(--slate-pale); }
.famsheet__body { margin: 0 0 var(--s4); font-size: 15px; line-height: 1.65; }
.famsheet__foot { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }

@media (max-width: 560px) {
  .fammsg__when { display: none; }
}

/* A time somebody entered is not a reading from the door, and a parent has a
   right to know which is which. */
.famrow__byhand {
  display: inline-block;
  margin-right: 6px;
  padding: 1px 7px;
  border-radius: 10px;
  background: var(--field);
  color: var(--slate);
  font-size: 11.5px;
}

/* --------------------------------------------------------------------------
   Absences, not a percentage

   The parish allows three and counts every five Masses missed as one more. A
   percentage said something different — three absences out of ten classes is
   seventy per cent, which would fail a child the parish considers fine.
   -------------------------------------------------------------------------- */
.famstand__lead { display: flex; align-items: baseline; gap: 9px; margin: 4px 0 0; }
.famstand__n { font-family: var(--font-display); font-size: 30px; line-height: 1; }
.famstand__n.is-over { color: var(--stop); }

.famstand__pips { display: flex; gap: 5px; margin: 12px 0 14px; }
.famstand__pip {
  flex: 1;
  height: 7px;
  border-radius: 4px;
  background: var(--rule-soft);
}
.famstand__pip.is-used { background: var(--warn); }
.famstand__pip.is-over { background: var(--stop); }
.famstand__pip--extra { flex: 0 0 14px; opacity: .55; }

.famstand__rows { font-size: 14px; color: var(--slate); }
.famstand__row {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  padding: 6px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.famstand__row small { display: block; font-size: 12px; color: var(--slate-pale); margin-top: 1px; }
.famstand__v { color: var(--ink); text-align: right; white-space: nowrap; }
.famstand__v.is-over { color: var(--stop); }

.famstand__row--total { border-bottom: 0; padding-top: 9px; font-weight: 600; }
.famstand__row--total span { color: var(--ink); }

.famstand__warn { margin-top: var(--s3); }

/* Asking for an absence to be excused. */
.famrow__ask {
  display: block;
  margin-top: 3px;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--ink-link, #2f5fd0);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.famrow__asked, .famrow__excused {
  display: block;
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--slate-pale);
  font-weight: 400;
}
.famrow__excused { color: var(--ok); }

.famexcuse__who { margin: 0 0 2px; font-size: 15px; font-weight: 600; }
.famexcuse__list { display: flex; flex-direction: column; gap: 1px; margin: var(--s3) 0; }
.famexcuse__opt {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: var(--radius-sm);
  font-size: 14px; cursor: pointer;
}
.famexcuse__opt:hover { background: var(--field); }
.famexcuse__opt input { flex: none; }
.famexcuse__note { padding-left: 10px; }
.famexcuse__note textarea {
  width: 100%; border: 1px solid var(--rule); border-radius: var(--radius-sm);
  padding: 9px 11px; font: inherit; font-size: 14px; resize: vertical;
}
.famexcuse__count { display: flex; justify-content: space-between; margin-top: 4px; }

/* --------------------------------------------------------------------------
   The road through the programme

   Four years in order. What came before is drawn as done because a child in
   the Communion year has sat through the one before it — but nothing here
   claims a sacrament was received: that register belongs to the parish.
   -------------------------------------------------------------------------- */
.fampath__now { margin: 2px 0 0; font-size: 21px; }

.fampath { list-style: none; margin: var(--s4) 0 0; padding: 0; }
.fampath__step {
  display: flex;
  gap: var(--s3);
  padding-bottom: var(--s4);
  position: relative;
}
.fampath__step:last-child { padding-bottom: 0; }

/* The line joining one year to the next. */
.fampath__step:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 5px; top: 16px; bottom: 4px;
  width: 1.5px;
  background: var(--rule-soft);
}
.fampath__step.is-done::before,
.fampath__step.is-now::before { background: var(--rule); }

.fampath__dot {
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 1.5px solid var(--rule);
  flex: none;
  margin-top: 4px;
  background: var(--paper);
  z-index: 1;
}
.fampath__step.is-done .fampath__dot { background: var(--ok); border-color: var(--ok); }
.fampath__step.is-now  .fampath__dot {
  background: var(--ink-link, #2f5fd0);
  border-color: var(--ink-link, #2f5fd0);
  box-shadow: 0 0 0 3px var(--field);
}

.fampath__what { flex: 1; font-size: 15px; color: var(--slate); }
.fampath__step.is-now .fampath__what { color: var(--ink); }
.fampath__what small { display: block; font-size: 12.5px; color: var(--slate-pale); margin-top: 1px; }
.fampath__step.is-now .fampath__what small { color: var(--ink-link, #2f5fd0); }

.fampath__go { margin: var(--s4) 0 0; padding-top: var(--s3); border-top: 1px solid var(--rule-soft); }
.famnote { font-size: 13px; color: var(--slate); }

/* Twelve answers open at once is a wall nobody reads. */
.famhelp { padding: 0; }
.famhelp__q { border-bottom: 1px solid var(--rule-soft); }
.famhelp__q:last-child { border-bottom: 0; }

.famhelp__q summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding: 14px var(--s4);
  font-size: 15px;
  cursor: pointer;
  list-style: none;
}
.famhelp__q summary::-webkit-details-marker { display: none; }
.famhelp__q summary:hover { background: var(--field); }
.famhelp__q summary svg { flex: none; color: var(--slate-pale); transition: transform .15s; }
.famhelp__q[open] summary svg { transform: rotate(180deg); }
.famhelp__q[open] summary { background: var(--field); }

.famhelp__q p {
  margin: 0;
  padding: 0 var(--s4) 15px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--slate);
  background: var(--field);
}

/* Somebody else the family lets look. */
.famguests { margin: var(--s4) 0; }
.famguest {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding: 11px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.famguest:last-child { border-bottom: 0; }
.famguest__name { display: block; font-size: 15px; }
.famguest__meta { display: block; font-size: 12.5px; color: var(--slate-pale); margin-top: 1px; }
.famguest__waiting { color: var(--warn); }
.famguest__x {
  border: 0; background: none; padding: 0; font: inherit;
  font-size: 13px; color: var(--ink-link, #2f5fd0);
  cursor: pointer; white-space: nowrap;
}
.famguests__none { margin: var(--s4) 0; color: var(--slate-pale); font-size: 14px; }

.famguest__ask { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.famguest__ask input {
  flex: 1;
  min-width: 170px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font: inherit;
  font-size: 14px;
}
.famguests__yours { margin: var(--s3) 0 0; font-size: 12.5px; color: var(--slate-pale); line-height: 1.6; }

/* The drawing beside the word: on a desktop it helps the eye find a row, and
   on a phone it lets the word be short enough that four fit across. */
.famsidenav__icon { display: flex; flex: none; color: var(--slate-pale); }
.famsidenav__item.is-on .famsidenav__icon { color: var(--ink); }

@media (max-width: 760px) {
  /* Four across, no sliding. A row that scrolls sideways hides its last
     entry, and the last entry is the one nobody finds. */
  .famsidenav { overflow-x: visible; gap: 2px; }
  .famsidenav .famsidenav__item {
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
    white-space: normal;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 8px 4px;
    text-align: center;
    font-size: 11px;
    line-height: 1.25;
  }
  .famsidenav__word {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
  }
  .famsidenav__icon svg { width: 17px; height: 17px; }
}

/* The bands say what they mean: green is on time, amber is the grace
   that still counts as on time, red is late, and the dark end is past
   the point where an arrival counts at all. */

/* Blue arrives, amber leaves. The arrival lands on the pale end of the
   bar and the departure on the dark one, so neither disappears. */
.fambar2__a.is-in  { color: #378ADD; }
.fambar2__a.is-out { color: #EF9F27; }

/* The stem marks the exact point on the bar; the arrow above it says
   which way. Blue arrives, amber leaves. */
.fambar2__stem { display: block; width: 3px; height: 9px;
  margin: 0 auto -9px; z-index: 3; }

.fambar2__stem.is-in  { background: #378ADD; }
.fambar2__stem.is-out { background: #EF9F27; }

/* The arrow points at the bar, so it sits against it. */
.fambar2__a { display: block; line-height: 0.8; margin-bottom: 1px; }

/* Each swatch belongs to the word after it, not to the gap before. */
.famkey__c { display: inline-block; width: 18px; height: 9px;
  border-radius: 4px; vertical-align: -1px; margin-right: 6px;
  margin-left: 0; }

/* A weekend was a card of its own, so the tab was a stack of boxes at
   different widths while classes was one list. Same list, same widths,
   same place for the bar. */
.famweek { border: 0; border-radius: 0; margin: 0;
  background: var(--paper, #fff); }
.famweek:first-of-type { border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.famweek:last-of-type { border-radius: 0 0 var(--radius-sm) var(--radius-sm); }
.famweek + .famweek { border-top: 1px solid var(--rule-soft); }
.famweek__head { background: none; padding: var(--s3) var(--s5) 0;
  border: 0; }
.famweek .famrow { padding-top: 0; padding-bottom: var(--s4);
  margin-top: 0; }
.famweek__head { padding-bottom: 0; }
.famweek .famrow__when { line-height: 1.35; }
.famweek__when { font-size: 14px; font-weight: 500; }

/* Five service times down the left pushed the bar off to the right and
   made the row three lines tall. The column is the width it is in
   classes, and what does not fit is folded to one line. */
.famweek .famrow__when { width: 190px; flex: none; }
.famweek .famrow__times { display: -webkit-box; -webkit-line-clamp: 1;
  -webkit-box-orient: vertical; overflow: hidden; }

/* The tick that asks whether there is a note, and the two ways of
   sending one that appear when there is. */
.famexcuse__proof { border-top: 1px solid var(--rule-soft, #dde3ee);
  margin-top: 14px; padding-top: 12px; }
.famexcuse__has { display: flex; align-items: center; gap: 8px;
  font-size: 14px; cursor: pointer; }
.famexcuse__pick { margin-top: 11px; }
.famexcuse__pick[hidden] { display: none; }
.famexcuse__two { display: flex; gap: 8px; }
.famexcuse__two .fambtn { flex: 1; }

/* The bar inside today's card: the same bar as the register, with room
   around it because it sits under a sentence rather than in a table. */
.famtoday__bar { margin: 14px 0 4px; }
