/* Freedom Institute SIS -- shared styles.
   Navy #101D49 and red #B9291D are the institute's marks. The interface stays
   quiet so the data reads first: this is a tool people use for six hours a day,
   not a marketing page. */

:root {
  --navy: #101D49;
  --navy-700: #1b2c66;
  --navy-300: #6675a8;
  --red: #B9291D;
  --red-dark: #972016;

  --ink: #16181d;
  --ink-soft: #4a4f5c;
  --ink-faint: #7a8090;
  --line: #dfe3ec;
  --line-soft: #edeff5;
  --bg: #f5f6fa;
  --panel: #ffffff;

  --ok: #1c7a4a;
  --ok-bg: #e6f4ec;
  --warn: #9a6207;
  --warn-bg: #fdf3e0;
  --err: #b3261e;
  --err-bg: #fceceb;

  /* A class grade at a glance (Nathan, 2026-09-17): an A or a B green, a C
     yellow, a D or an F red. Darker than --ok/--warn/--err so a letter reads
     on its own tint, and every chip keeps a border so colour is never the
     only thing carrying the message. */
  --gb-good: #14713f; --gb-good-bg: #e4f3ea; --gb-good-line: #a6d7bc;
  --gb-fair: #8a5a00; --gb-fair-bg: #fdf1d7; --gb-fair-line: #e7cd93;
  --gb-poor: #a81f16; --gb-poor-bg: #fbe6e4; --gb-poor-line: #edb2ac;

  --radius: 6px;
  --shadow: 0 1px 2px rgba(16, 29, 73, .06), 0 4px 14px rgba(16, 29, 73, .05);
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  --sans: "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--sans);
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--navy-700); text-decoration: none; }
a:hover { text-decoration: underline; }

/* "Install this app" -- rides the Freedom Institute header row, far right.
   Gone once the app is actually installed. */
.install-btn {
  margin-left: auto; align-self: center; flex: none;
  background: rgba(255, 255, 255, .12); color: #fff;
  border: 1px solid rgba(255, 255, 255, .4); border-radius: var(--radius);
  padding: 4px 9px; font-size: 11.5px; font-weight: 600; cursor: pointer;
  white-space: nowrap;
}
.install-btn:hover { background: rgba(255, 255, 255, .22); }
.sidebar .brand { flex-wrap: wrap; }

/* ---------- app shell ---------- */

.app { display: grid; grid-template-columns: 216px 1fr; min-height: 100vh; }

.sidebar {
  background: var(--navy);
  color: #fff;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}
.sidebar .brand {
  padding: 18px 18px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, .12);
}
.sidebar .brand strong { display: block; font-size: 15px; letter-spacing: .2px; }
.sidebar .brand span { display: block; font-size: 11px; color: #9aa6cd; margin-top: 2px; }

/* The one door into Freedom Learn, the learning site (Nathan, 2026-09-12). */
.lms-launch {
  display: block; margin: 12px 12px 0; padding: 8px 10px; border-radius: var(--radius);
  background: var(--red); color: #fff; font-weight: 650; font-size: 13.5px; text-align: center;
}
.lms-launch:hover { background: var(--red-dark); color: #fff; text-decoration: none; }
.portal-head .lms-launch { display: inline-block; margin: 0; align-self: center; }
/* Shown while an administrator previews someone: the account has the button,
   but it opens as the administrator, so it is not a link here. */
.lms-launch.off { opacity: .45; cursor: default; }
.lms-launch.off:hover { background: var(--red); }

.sidebar nav { padding: 10px 8px; flex: 1; overflow-y: auto; }
.sidebar nav a {
  display: block;
  padding: 8px 10px;
  margin-bottom: 1px;
  border-radius: var(--radius);
  color: #c6cde4;
  font-size: 13.5px;
}
.sidebar nav a:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.sidebar nav a.active { background: var(--red); color: #fff; font-weight: 600; }
.sidebar nav .group {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .8px;
  color: #7d89b4; padding: 14px 10px 5px;
}
/* A count riding a sidebar link: how many campuses are past due for a drill. */
.sidebar nav a .nav-badge {
  float: right; min-width: 20px; padding: 0 6px; margin-left: 6px;
  border-radius: 10px; background: var(--red); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 20px; text-align: center;
}
.sidebar nav a.active .nav-badge { background: #fff; color: var(--red); }
.sidebar .foot {
  padding: 12px 14px; border-top: 1px solid rgba(255, 255, 255, .12); font-size: 12px;
}
.sidebar .foot .who { color: #fff; font-weight: 600; }
.sidebar .foot .role { color: #9aa6cd; text-transform: capitalize; }
.sidebar .foot button {
  margin-top: 8px; background: none; border: 1px solid rgba(255, 255, 255, .25);
  color: #c6cde4; padding: 4px 10px; border-radius: var(--radius); cursor: pointer; font-size: 12px;
}
.sidebar .foot button:hover { background: rgba(255, 255, 255, .1); color: #fff; }

.main { min-width: 0; }
.topbar {
  background: var(--panel); border-bottom: 1px solid var(--line);
  padding: 14px 24px; display: flex; align-items: center; gap: 16px;
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { font-size: 18px; margin: 0; font-weight: 650; letter-spacing: -.2px; }
.topbar .sub { color: var(--ink-faint); font-size: 12.5px; }
.topbar .spacer { flex: 1; }

.content { padding: 22px 24px 60px; max-width: 1240px; }

/* School year picker, top right. When you are looking at a year that is not the
   school's current one, it turns amber. That state is easy to forget you are in
   and expensive to forget: grades and enrollments would land in the wrong year. */
.year-select {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 10px 4px 12px; border: 1px solid var(--line);
  border-radius: var(--radius); background: #fafbfd;
}
.year-select label {
  margin: 0; font-size: 10.5px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--ink-faint); white-space: nowrap;
}
.year-select select {
  width: auto; min-width: 108px; border: none; background: transparent;
  font-weight: 700; font-size: 14px; color: var(--navy); padding: 3px 2px; cursor: pointer;
}
.year-select select:focus { box-shadow: none; }
/* The campus slot is present on every page but only filled where a page is
   campus-scoped; empty, it would still take a gap in the flex row. */
#campus-picker:empty { display: none; }

/* Stat tiles that link somewhere behave like tiles, not like underlined text,
   and lift slightly so the hand knows they are doors. */
a.stat { display: block; color: inherit; text-decoration: none; }
a.stat:hover { border-color: var(--navy-300); box-shadow: 0 2px 10px rgba(16,29,73,.12);
               transform: translateY(-1px); }

/* ---------- brand ---------- */
/* The crest sits with the wordmark; the red rule under the topbar is the same
   red the institute prints. Decoration stays out of the data's way. */
.brand { display: flex; align-items: center; gap: 10px; }
/* The crest is a navy eagle; on the navy sidebar it needs its own ground. A
   white chip reads as a badge rather than a patch, and the logo keeps its own
   colors instead of being recolored. */
.brand-crest { height: 46px; width: 46px; flex: none; object-fit: contain;
               background: #fff; border-radius: 8px; padding: 4px;
               box-shadow: 0 1px 3px rgba(0,0,0,.35); }

.topbar { border-top: 3px solid var(--red); }
body.off-year .topbar { border-top-color: var(--navy); }

.sidebar nav a.active {
  box-shadow: inset 3px 0 0 #fff;
}

/* Section headers pick up the brand rule. */
.panel h2 { border-left: 3px solid var(--red); padding-left: 11px; }

/* Stat tiles get the navy/red identity: navy number, red underscore. */
.stat .n { position: relative; padding-bottom: 6px; }
.stat .n::after { content: ''; position: absolute; left: 0; bottom: 0;
                  width: 26px; height: 3px; border-radius: 2px; background: var(--red); }
.stat.alert .n::after { background: var(--warn); }

/* The eagle keeps watch over the sidebar footer, faintly. */
.sidebar { position: relative; }
.sidebar::after {
  content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 180px;
  background: url('/assets/freedom-eagle.png') no-repeat center bottom 8px / 150px auto;
  /* Navy art on a navy wall is invisible; inverted to a white ghost it reads. */
  filter: brightness(0) invert(1);
  opacity: .10; pointer-events: none;
}
.sidebar .foot { position: relative; z-index: 1; }

/* Empty states carry a whisper of the crest instead of dead air. */
.empty { position: relative; }
.empty::before {
  content: ''; display: block; margin: 0 auto 8px; width: 44px; height: 44px;
  background: url('/assets/freedom-eagle.png') no-repeat center / contain;
  opacity: .18;
}

/* "View as" banner. Amber rather than red: nothing is wrong, but you are not
   where you think you are, and every page has to say so. */
.viewas-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  padding: 8px 16px; font-size: 13px;
  background: #8a5a00; color: #fff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .18);
}
.viewas-bar strong { font-weight: 700; }
.viewas-bar .btn {
  background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .5); color: #fff;
}
.viewas-bar .btn:hover { background: rgba(255, 255, 255, .28); }
body.viewing-as .app { padding-top: 37px; }
body.viewing-as .topbar { top: 37px; }
/* Off the current school year, the whole header goes red. Working in the wrong
   year is the single easiest mistake to make in a system like this and the
   most annoying to unpick, so the warning is the header itself, not a badge
   somebody has to notice. */
body.off-year .topbar {
  background: var(--red);
  border-bottom-color: var(--red-dark);
}
body.off-year .topbar h1 { color: #fff; }
body.off-year .topbar .sub { color: rgba(255, 255, 255, .88); }
body.off-year .topbar .btn {
  background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .45); color: #fff;
}
body.off-year .topbar .btn:hover { background: rgba(255, 255, 255, .26); }
body.off-year .topbar .btn.primary {
  background: #fff; border-color: #fff; color: var(--red-dark);
}
body.off-year .year-select {
  background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .5);
}
body.off-year .year-select label { color: rgba(255, 255, 255, .9); }
body.off-year .year-select select { color: #fff; }
body.off-year .year-select select option { color: var(--ink); }

/* ---------- panels ---------- */

.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); margin-bottom: 18px;
}
.panel > h2 {
  margin: 0; padding: 12px 16px; font-size: 13px; font-weight: 650;
  text-transform: uppercase; letter-spacing: .6px; color: var(--ink-soft);
  border-bottom: 1px solid var(--line-soft);
}
.panel .body { padding: 16px; }
.panel .body.flush { padding: 0; }

.grid { display: grid; gap: 16px; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* ---------- stat tiles ---------- */

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px; box-shadow: var(--shadow);
}
.stat .n { font-size: 26px; font-weight: 660; color: var(--navy); line-height: 1.1; }
.stat .k { font-size: 11.5px; text-transform: uppercase; letter-spacing: .6px; color: var(--ink-faint); margin-top: 4px; }
.stat.alert .n { color: var(--red); }

/* ---------- tables ---------- */

table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
thead th {
  text-align: left; padding: 9px 14px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .6px; color: var(--ink-faint); border-bottom: 1px solid var(--line);
  background: #fafbfd; font-weight: 650; white-space: nowrap;
}
tbody td { padding: 9px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover { background: #f7f9fd; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); font-size: 12.5px; }

/* ---------- forms ---------- */

label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-soft); margin-bottom: 4px; }
input[type=text], input[type=email], input[type=password], input[type=date],
input[type=tel], input[type=number], select, textarea {
  width: 100%; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--radius);
  font-family: inherit; font-size: 13.5px; color: var(--ink); background: #fff;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--navy-300); box-shadow: 0 0 0 3px rgba(16, 29, 73, .08);
}
textarea { resize: vertical; min-height: 90px; line-height: 1.55; }
.field { margin-bottom: 13px; }
.fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 14px; }
.check { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.check input { width: auto; margin: 0; }
.check label { margin: 0; font-weight: 500; color: var(--ink); font-size: 13px; }
.hint { font-size: 12px; color: var(--ink-faint); margin-top: 4px; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: #fff; color: var(--ink); font-size: 13.5px; font-weight: 600;
  font-family: inherit; cursor: pointer;
}
.btn:hover { background: #f4f6fa; text-decoration: none; }
.btn.primary { background: var(--navy); border-color: var(--navy); color: #fff; }
.btn.primary:hover { background: var(--navy-700); }
.btn.danger { background: var(--red); border-color: var(--red); color: #fff; }
.btn.danger:hover { background: var(--red-dark); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--navy-700); }
.btn.ghost:hover { background: #eef1f7; }
.btn.sm { padding: 4px 9px; font-size: 12.5px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ---------- pills and badges ---------- */

.pill {
  display: inline-block; padding: 2px 8px; border-radius: 20px; font-size: 11.5px;
  font-weight: 600; background: var(--line-soft); color: var(--ink-soft); white-space: nowrap;
}
.pill.ok { background: var(--ok-bg); color: var(--ok); }

/* The engagement columns on a send ledger: narrow, centred, and read down the
   page rather than across it, so a send is scannable at a glance. */
th.mid, td.mid { text-align: center; width: 96px; }
.tick { color: #1f7a3d; font-size: 15px; font-weight: bold; line-height: 1; }
.pill.warn { background: var(--warn-bg); color: var(--warn); }
.pill.err { background: var(--err-bg); color: var(--err); }
.pill.navy { background: #e8ebf5; color: var(--navy); }

/* The running class grade, wherever it is shown: gradebook, grade-by-student,
   a coach's screen, the family portal. One chip, one scale, one set of
   colours -- the percent and the letter are always there in words, so the
   colour only repeats what the text already says. */
.gpill {
  display: inline-flex; align-items: baseline; gap: 6px; padding: 2px 10px;
  border-radius: 20px; font-size: 12.5px; font-weight: 700; white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft); background: var(--line-soft); border: 1px solid var(--line);
}
.gpill b { font-size: 13px; font-weight: 800; }
.gpill.good { color: var(--gb-good); background: var(--gb-good-bg); border-color: var(--gb-good-line); }
.gpill.fair { color: var(--gb-fair); background: var(--gb-fair-bg); border-color: var(--gb-fair-line); }
.gpill.poor { color: var(--gb-poor); background: var(--gb-poor-bg); border-color: var(--gb-poor-line); }
.gpill.lg { font-size: 15px; padding: 3px 12px; }
.gpill.lg b { font-size: 16px; }

/* ---------- notices ---------- */

.notice { padding: 11px 14px; border-radius: var(--radius); font-size: 13px; margin-bottom: 14px; border: 1px solid; }
.notice.info { background: #eef2fb; border-color: #cfd8ee; color: var(--navy); }
.notice.warn { background: var(--warn-bg); border-color: #f0dcb4; color: var(--warn); }
.notice.err  { background: var(--err-bg); border-color: #f2cbc8; color: var(--err); }
.notice.ok   { background: var(--ok-bg); border-color: #c2e2d0; color: var(--ok); }
.notice strong { font-weight: 700; }

.empty { padding: 34px 20px; text-align: center; color: var(--ink-faint); font-size: 13.5px; }

/* ---------- toast ---------- */

#toast {
  position: fixed; right: 20px; bottom: 20px; z-index: 200;
  display: flex; flex-direction: column; gap: 8px;
}
#toast div {
  background: var(--navy); color: #fff; padding: 10px 15px; border-radius: var(--radius);
  font-size: 13.5px; box-shadow: 0 6px 22px rgba(16, 29, 73, .25); max-width: 340px;
  animation: rise .18s ease-out;
}
#toast div.err { background: var(--red); }
@keyframes rise { from { transform: translateY(8px); opacity: 0; } }

/* ---------- modal ---------- */

.modal-bg {
  position: fixed; inset: 0; background: rgba(16, 29, 73, .45); z-index: 100;
  display: flex; align-items: flex-start; justify-content: center; padding: 50px 20px;
  overflow-y: auto;
}
.modal {
  background: #fff; border-radius: 8px; width: 100%; max-width: 620px;
  box-shadow: 0 20px 60px rgba(16, 29, 73, .3);
}
.modal header {
  padding: 15px 20px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
}
.modal header h3 { margin: 0; font-size: 16px; }
.modal .body { padding: 20px; }
.modal footer {
  padding: 13px 20px; border-top: 1px solid var(--line); background: #fafbfd;
  display: flex; justify-content: flex-end; gap: 8px; border-radius: 0 0 8px 8px;
}
.x { background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: var(--ink-faint); }

/* ---------- tabs ---------- */

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 18px; }
.tabs button {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 9px 15px; font-size: 13.5px; font-weight: 600; color: var(--ink-faint);
  cursor: pointer; font-family: inherit;
}
.tabs button:hover { color: var(--ink); }
.tabs button.active { color: var(--navy); border-bottom-color: var(--red); }

/* ---------- login ---------- */

.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, var(--navy) 0%, #0a1230 100%); padding: 20px;
}
.login-card {
  background: #fff; border-radius: 10px; width: 100%; max-width: 380px;
  padding: 32px 30px; box-shadow: 0 24px 70px rgba(0, 0, 0, .35);
}
.login-card h1 { margin: 0 0 3px; font-size: 21px; color: var(--navy); }
.login-card .sub { color: var(--ink-faint); font-size: 13px; margin-bottom: 22px; }
.login-card .btn { width: 100%; justify-content: center; padding: 9px; }

@media (max-width: 860px) {
  /* Phone shell: the sidebar folds into a compact header -- crest and name on
     one line, the nav as a single swipeable row of chips, who-you-are and
     Sign out sharing one row. Nothing is removed, everything is tightened. */
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar, .main { min-width: 0; max-width: 100%; }
  .sidebar { position: static; height: auto; }
  .sidebar::after { display: none; }

  .sidebar .brand { padding: 10px 14px 8px; }
  .brand-crest { height: 34px; width: 34px; padding: 3px; }
  .sidebar .brand strong { font-size: 14px; }
  .sidebar .brand span { font-size: 10px; margin-top: 0; }

  .sidebar nav { display: flex; flex-wrap: nowrap; overflow-x: auto;
                 -webkit-overflow-scrolling: touch; gap: 4px; padding: 6px 10px;
                 scrollbar-width: none; }
  .sidebar nav::-webkit-scrollbar { display: none; }
  .sidebar nav a { white-space: nowrap; padding: 6px 11px; font-size: 12.5px;
                   margin-bottom: 0; }
  .sidebar nav .group { display: none; }

  .sidebar .foot { display: flex; align-items: center; gap: 8px;
                   padding: 7px 14px; }
  .sidebar .foot .who { font-size: 12px; }
  .sidebar .foot .role { font-size: 11px; }
  .sidebar .foot button { margin-top: 0; margin-left: auto; flex: none; }

  /* Topbar: title first, then the pickers and buttons flow onto their own
     tidy rows instead of shoving each other off the screen. */
  .topbar { position: static; flex-wrap: wrap; padding: 10px 14px;
            gap: 8px 10px; }
  body.viewing-as .topbar { top: auto; }
  .topbar h1 { font-size: 17px; }
  .topbar > div:first-child { flex: 1 1 55%; min-width: 0; }
  .topbar .spacer { display: none; }
  #topbar-actions { order: 5; width: 100%; }
  #topbar-actions .btn { padding: 5px 10px; font-size: 12.5px; }
  #view-picker, #campus-picker, #year-picker { max-width: 100%; }
  .year-select { padding: 3px 8px; gap: 6px; }
  .year-select label { font-size: 9.5px; }
  .year-select select { min-width: 0; font-size: 13px; }

  .content { padding: 14px 12px 40px; }
  .panel .body { padding: 12px; }
  .stats { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 9px; }
  .stat { padding: 11px 13px; }
  .stat .n { font-size: 22px; }
  .tabs { overflow-x: auto; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs button { white-space: nowrap; padding: 8px 11px; }
}

/* ----- weekly schedule grid (shared: staff student page + family portal;
   markup built by js/schedule-grid.js) ----- */
  /* Weekly schedule grid. Classes are placed by clock time rather than listed,
     because "do these two collide?" and "how long is the gap after lunch?" are
     questions a list cannot answer at a glance. */
.wk { display: grid; grid-template-columns: 76px repeat(5, minmax(140px, 1fr)) minmax(150px, 1fr);
        /* width: max-content is what makes the phone swipe real: without it
           the grid box stays screen-width and the columns spill invisibly
           past every container, so the page pans into blank space instead of
           the grid scrolling. */
        width: max-content; min-width: 100%;
        border: 1px solid var(--wk-line); border-radius: var(--radius);
        overflow: hidden; background: #fff; }
.wk-head { background: #b9c8dd; color: #2b3340; text-align: center;
             font-weight: 600; padding: 8px 6px; font-size: 13px;
             border-left: 1px solid var(--wk-line); border-bottom: 1px solid var(--wk-line); }
.wk-head:first-child { border-left: none; }
.wk-head .d { font-weight: 400; font-size: 12px; color: #46505f; }
.wk-head.today { background: var(--navy); color: #fff; }
.wk-head.today .d { color: #c3ccdf; }

.wk-gutter { position: relative; border-right: 1px solid var(--wk-line); background: #fff; }
.wk-gutter .hr { position: absolute; left: 0; right: 0; text-align: right;
                   padding-right: 8px; font-size: 12px; font-weight: 600;
                   color: #3d444f; }
.wk-gutter .hr.alt { background: #dfe7f1; }
.wk-gutter .hr.hidden-hour { color: transparent; }

.wk-col { position: relative; border-left: 1px solid var(--wk-line);
            background: repeating-linear-gradient(45deg, #f0f0f0 0 6px, #e2e2e2 6px 12px); }
  /* The open school day is painted white on top of the hatching, so anything
     still showing hatch is outside the bell schedule. */
.wk-open { position: absolute; left: 0; right: 0; background: #fff; }

.wk-block { position: absolute; left: 2px; right: 2px; overflow: hidden;
              border: 1px solid rgba(0,0,0,.10); border-radius: 3px;
              padding: 6px 8px; font-size: 12.5px; line-height: 1.35;
              cursor: pointer; }
.wk-block:hover { border-color: var(--navy-300); }
.wk-block .t { font-weight: 700; color: #1d2330; }
.wk-block .who, .wk-block .rm, .wk-block .tm { color: #444b58; }
.wk-block .tm { margin-top: 4px; }
.wk-block.narrow { padding: 4px 6px; font-size: 11px; line-height: 1.22; }
.wk-block.narrow .tm { margin-top: 1px; }
  /* Sharing the width with another class leaves no room to wrap. Each line
     gets one line, the room drops out (it is on the card you get by
     clicking), and the time -- the reason you looked -- always survives. */
.wk-block.tight .t, .wk-block.tight .who, .wk-block.tight .tm {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wk-block.tight .rm { display: none; }

.wk-none { position: absolute; top: 8px; left: 0; right: 0; text-align: center;
             font-weight: 600; color: #4a5160; font-size: 13px; }
.wk-col.empty-day { background: #f2f2f2; }

  /* Anywhere / dual-enrolment work has no hour on the timetable, so it gets a
     column of its own rather than an invented slot inside the week. Flat, not
     hatched: nothing is missing here, it simply is not clock-bound. */
.wk-col.anytime { background: #fff; padding: 6px; overflow-y: auto; }
.wk-col.anytime .wk-block { position: static; margin-bottom: 5px; height: auto !important;
                              left: auto; width: auto; }

  /* Happening right now. Every other block on the grid is a plan; this one is
     where the student is standing, so it is the only saturated colour on the
     page and it wins the stacking order over its neighbours. */
.wk-block.now { background: #cfe0ff !important; border-color: var(--navy);
                box-shadow: 0 0 0 2px var(--navy), 0 4px 12px rgba(16,29,73,.25);
                z-index: 3; }
.wk-block.now .t { color: var(--navy); padding-right: 34px; }
.wk-block.now .who, .wk-block.now .rm, .wk-block.now .tm { color: #26324f; }
.wk-block.now::after { content: 'NOW'; position: absolute; top: 3px; right: 3px;
                       background: var(--navy); color: #fff; font-size: 9px;
                       font-weight: 700; letter-spacing: .07em; line-height: 1;
                       padding: 3px 4px; border-radius: 3px; }
  /* Between classes: the one being walked to, outlined but not filled, so a
     passing period does not read as "nowhere to be". */
.wk-block.next { border-color: var(--navy-300); box-shadow: 0 0 0 2px rgba(102,117,168,.55); }
.wk-block.next .t { padding-right: 36px; }
.wk-block.next::after { content: 'NEXT'; position: absolute; top: 3px; right: 3px;
                        background: #eef2fa; color: var(--navy-700); font-size: 9px;
                        font-weight: 700; letter-spacing: .07em; line-height: 1;
                        padding: 3px 4px; border-radius: 3px;
                        border: 1px solid var(--navy-300); }

  /* The current minute, drawn across today only. Red because the blue block is
     already saying "this class" -- the line is saying "this instant". */
.wk-now { position: absolute; left: 0; right: 0; height: 0; z-index: 4;
          border-top: 2px solid var(--red); pointer-events: none; }
.wk-now::before { content: ''; position: absolute; left: -1px; top: -4px;
                  width: 7px; height: 7px; border-radius: 50%; background: var(--red); }
  /* The reading for that line, parked in the hour gutter as a solid tab so it
     wins over whatever hour label it lands on. */
.wk-now-time { position: absolute; left: 2px; right: 2px; text-align: right;
               margin-top: -9px; z-index: 5;
               background: var(--red); color: #fff; font-size: 10.5px; font-weight: 700;
               line-height: 1; letter-spacing: .01em; padding: 3px 5px; border-radius: 3px;
               white-space: nowrap; pointer-events: none; }

  /* Same answer in the list view. */
tr.now-row > td { background: #cfe0ff; }
tr.now-row > td:first-child { box-shadow: inset 3px 0 0 var(--navy); }

.wk-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch;
           /* Swipes settle on day boundaries rather than half-columns. */
           scroll-snap-type: x proximity; }
.wk-head { scroll-snap-align: start; }
@media (max-width: 700px) {
  /* Phone: slightly tighter columns so each swipe reveals a full day. */
  .wk { grid-template-columns: 60px repeat(5, minmax(128px, 1fr)) minmax(136px, 1fr); }
}
/* On a phone the week is wider than the screen; say so instead of hoping
   the swipe is discovered. */
.wk-swipe-hint { display: none; }
@media (max-width: 700px) {
  .wk-swipe-hint { display: block; text-align: center; font-size: 12.5px;
                   color: var(--ink-faint); padding: 0 0 8px; }
}

/* Coaching notes sheet: cells that look like a grid, not a form. */
.notes-sheet td { padding: 4px 6px; vertical-align: top; }
.notes-sheet .cell { width: 100%; border: 1px solid transparent; border-radius: 4px; padding: 5px 7px;
                     background: transparent; font: inherit; color: inherit; resize: none; line-height: 1.35; }
.notes-sheet .cell:hover { border-color: var(--line); background: #fff; }
.notes-sheet .cell:focus { outline: none; border-color: var(--navy); background: #fff;
                           box-shadow: 0 0 0 2px rgba(11,24,68,.08); }
.notes-sheet tr.new { background: #fbfcfe; }
.notes-sheet tr.new .cell { border-color: var(--line-soft); background: #fff; }
.notes-sheet .note-act { text-align: right; white-space: nowrap; }
.notes-sheet .note-save { visibility: hidden; }
.notes-sheet tr.new .note-save, .notes-sheet tr.dirty .note-save { visibility: visible; }
.notes-sheet .note-act .btn { padding: 2px 8px; opacity: .5; }
.notes-sheet tr:hover .note-act .btn { opacity: 1; }

:root { --wk-line: #9aa8bd; }
@media print {
    .wk-wrap { overflow: visible; }
    .wk-block { break-inside: avoid; }
  }

/* Printed schedule (schedule-grid.js printSchedule): a box at the end of the
   page that exists only on paper. While it prints, the rest of the page --
   sidebar, tabs, buttons, dialogs -- is switched off. */
#sched-print { display: none; }
@media print {
  body.printing-schedule > *:not(#sched-print) { display: none !important; }
  body.printing-schedule #sched-print { display: block; }
  #sched-print .sp-head { display: flex; justify-content: space-between; align-items: flex-end;
                          gap: 16px; padding-bottom: 6px; margin-bottom: 8px;
                          border-bottom: 2px solid #101d49; }
  #sched-print .sp-name { font-size: 19px; font-weight: 700; color: #101d49; }
  #sched-print .sp-week { font-size: 14px; font-weight: 650; color: #101d49; }
  #sched-print .sp-coach { font-size: 15px; font-weight: 700; color: #b9291d; }
  #sched-print .sp-right { text-align: right; }
  #sched-print .sp-sub { font-size: 11.5px; color: #555; }
  #sched-print .wk-wrap { overflow: visible; }
  #sched-print .wk { width: 100%; min-width: 0; zoom: .82;
                     grid-template-columns: 64px repeat(5, 1fr) 1fr; }
  #sched-print .wk-swipe-hint { display: none; }
  #sched-print .wk-block { cursor: default; }
  .wk-now, .wk-now-time { display: none !important; }
  .wk-block.now, .wk-block.next { box-shadow: none; }
  .wk-block.now::after, .wk-block.next::after { display: none; }
  #sched-print * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  #sched-print .sp-page { break-after: page; page-break-after: always; }
  #sched-print .sp-page:last-child { break-after: auto; page-break-after: auto; }

  /* Graduation sheets (grad-print.js) share the box; these are their own parts. */
  #sched-print .gp { font-size: 11.5px; color: #1c2136; }
  #sched-print .gp-summary { display: flex; justify-content: space-between; gap: 12px;
                             margin: 10px 0 12px; padding: 8px 10px; border-radius: 6px;
                             background: #eef1f8; font-weight: 600; }
  #sched-print .gp-summary.ok { background: #e7f4ea; }
  #sched-print .gp-pct { white-space: nowrap; }
  #sched-print .gp h3 { font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
                        color: #555; margin: 14px 0 6px; }
  #sched-print .gp-t { width: 100%; border-collapse: collapse; }
  #sched-print .gp-t th, #sched-print .gp-t td { padding: 5px 7px; border-bottom: 1px solid #d5dae6;
                                                 text-align: left; vertical-align: top; }
  #sched-print .gp-t th { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
                          color: #555; background: #f3f5fb; }
  #sched-print .gp-t .n { text-align: right; white-space: nowrap; }
  #sched-print .gp-narrow td:last-child { width: 90px; }
  #sched-print .gp-note { font-size: 10.5px; color: #666; }
  #sched-print .gp-ok { color: #1f7a3a; font-weight: 700; }
  #sched-print .gp-no { color: #b9291d; font-weight: 700; }
  #sched-print .gp-t tr { break-inside: avoid; }
}


/* Attendance by location, the dashboard panel (public/js/attendance-rates.js).
   One row per location, one percent per day; the average column carries the
   weight, today's column is tinted so the live cell is easy to find. */
.ar-tabs { margin-bottom: 12px; }
.ar-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
          flex-wrap: wrap; margin-bottom: 12px; }
.ar-title { font-size: 15px; font-weight: 650; color: var(--navy); }
.ar-controls { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ar-controls .btn.sm { font-size: 14px; min-width: 32px; justify-content: center; }
.ar-inline { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-weight: 600; }
.ar-inline input[type=date] { width: auto; }
.ar-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }
.ar-table th.mid, .ar-table td.mid { width: auto; min-width: 70px; }
.ar-table thead th, .ar-table tbody td { padding: 9px 10px; }
/* The location stays put while a long year scrolls sideways under it. */
.ar-table th:first-child, .ar-table td:first-child { position: sticky; left: 0; z-index: 1;
  white-space: nowrap; background: #fff; padding-left: 14px; }
.ar-table thead th:first-child { background: #fafbfd; }
.ar-table thead th { text-align: center; }
.ar-table thead th:first-child { text-align: left; }
.ar-sub { font-size: 11px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--ink-faint); margin-top: 2px; }
.ar-pct { display: inline-block; padding: 2px 9px; border-radius: 20px; border: 1px solid transparent;
          font-size: 14.5px; font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums; }
/* Same green / yellow / red as the gradebook; the number always carries the
   meaning too, so colour is never the only signal. */
.ar-pct.good { color: var(--gb-good); background: var(--gb-good-bg); border-color: var(--gb-good-line); }
.ar-pct.fair { color: var(--gb-fair); background: var(--gb-fair-bg); border-color: var(--gb-fair-line); }
.ar-pct.poor { color: var(--gb-poor); background: var(--gb-poor-bg); border-color: var(--gb-poor-line); }
.ar-avg { background: #f3f5fb; }
.ar-table .ar-avg { position: sticky; right: 0; z-index: 1; }
.ar-avg .ar-pct { font-weight: 800; }
.ar-key { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.ar-key .ar-pct { font-size: 12px; padding: 1px 9px; }
thead th.ar-avg { color: var(--navy); }
.ar-today { background: #fdf6e7; }
.ar-note { font-size: 11px; color: var(--ink-faint); margin-top: 2px; white-space: nowrap; }
.ar-off { font-size: 12.5px; font-weight: 650; color: var(--ink-faint); }
.ar-miss { font-size: 12.5px; color: var(--ink-soft); font-style: italic; }
.ar-all td, .ar-table .ar-all td:first-child { border-top: 2px solid var(--line); background: #fafbfd; }
.ar-all td.ar-avg { background: #eceff8; }
.ar-foot { margin: 10px 0 0; }
.ar-loading { opacity: .45; transition: opacity .15s; }
/* Download PDF / Email it to me, after the week arrows. */
.ar-out { display: inline-flex; gap: 6px; margin-left: 10px; }
.ar-controls .ar-out .btn.sm { font-size: 13px; }
@media (max-width: 600px) {
  .ar-table .ar-avg { position: static; }
  .ar-out { margin-left: 0; }
}
