/* =====================================================================
   School Hub - components
   Depends on theme.css. No colour, size or duration is hardcoded here.
   Mobile-first: the base rules target a 375px viewport.
   ===================================================================== */

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

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

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  /* Nothing rubber-bands sideways. Guards the no-horizontal-scroll rule. */
  overflow-x: hidden;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-tight);
  margin: 0;
}

p { margin: 0 0 var(--sp-3); }
p:last-child { margin-bottom: 0; }

a { color: var(--c-primary-bright); }

img, svg { max-width: 100%; }

/* Focus is always visible. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Screen-reader-only text. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link for keyboard users on the Chromebook. */
.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: calc(-1 * var(--tap-comfy) - var(--sp-4));
  z-index: var(--z-toast);
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-neon);
  color: var(--c-text-on-light);
  border-radius: var(--radius);
  font-weight: var(--fw-bold);
  text-decoration: none;
  transition: top var(--dur-fast) var(--ease);
}
.skip-link:focus { top: var(--sp-4); }

/* ---------------------------------------------------------------------
   APP FRAME
   The column is capped so the app still reads as a phone app on a
   Chromebook rather than stretching into a dashboard.
   --------------------------------------------------------------------- */
.app {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.app__main {
  flex: 1 1 auto;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--sp-4) var(--gutter);
  /* Reserve the bottom nav, the pinned quick-add bar, and the iPhone
     home indicator, so the last section is never trapped under them. */
  padding-bottom: calc(
    var(--nav-height) + var(--quickadd-height) + var(--sp-6) + env(safe-area-inset-bottom, 0px)
  );
}

/* ---------------------------------------------------------------------
   PAGE HEADER
   --------------------------------------------------------------------- */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

.page-head__title {
  font-size: var(--fs-h2);
  color: var(--c-text);
}

.page-head__sub {
  margin-top: var(--sp-1);
  font-size: var(--fs-body);
  color: var(--c-text-muted);
}

.eyebrow {
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

/* ---------------------------------------------------------------------
   CARD
   --------------------------------------------------------------------- */
.card {
  background: var(--c-surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-4);
}

.card + .card { margin-top: var(--sp-3); }

.card__title {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-display);
  margin: 0 0 var(--sp-2);
}

.card__body { color: var(--c-text-soft); }

/* Section heading above a group of cards. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  /* Equal space above and below, so a heading belongs to its section
     without crowding it. */
  margin: var(--sp-6) 0;
}
.section-head:first-child { margin-top: 0; }

/* When a heading opens its own <section> (the Links categories), the
   first-child rule above eats its top margin - so the gap moves onto the
   section boundary instead. Net result: 24px above every category
   heading and 24px below, exactly equal. */
[data-filter-group] + [data-filter-group] { margin-top: var(--sp-6); }

.section-head__title {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
  letter-spacing: var(--ls-display);
  /* Every word capitalized, per the design review: "Due Today", not
     "Due today". One rule here covers every section on every screen. */
  text-transform: capitalize;
}

.section-head__count {
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

/* When the slot on the right of a section heading is a link rather than a
   plain count, it is something people tap, so it gets the 48px floor.
   Negative margin keeps the heading visually tight despite the target. */
a.section-head__count {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  margin: calc(var(--tap-min) / -2 + 0.5em) 0;
  padding: 0 var(--sp-2);
  margin-right: calc(-1 * var(--sp-2));
  font-size: var(--fs-body);
  color: var(--c-primary-bright);
  text-decoration: none;
}
a.section-head__count:hover { color: var(--c-text); }

/* ---------------------------------------------------------------------
   BUTTONS - every variant clears the 48px floor
   --------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap-comfy);
  padding: 0 var(--sp-5);
  border: var(--border-strong);
  border-radius: var(--radius);
  background: var(--c-surface-raised);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              transform var(--dur-instant) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.btn:hover  { background: var(--c-surface-hover); }
.btn:active { transform: scale(0.97); }

.btn--primary {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-text-on-light);
  font-weight: var(--fw-bold);
}
.btn--primary:hover { background: var(--c-primary-bright); border-color: var(--c-primary-bright); }

.btn--ghost {
  background: transparent;
  border-color: var(--c-line);
  color: var(--c-text-soft);
}
.btn--ghost:hover { background: var(--c-surface); color: var(--c-text); }

.btn--block { width: 100%; }

.btn--large { min-height: var(--tap-large); font-size: var(--fs-body-lg); }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

/* ---------------------------------------------------------------------
   FORM CONTROLS
   16px minimum font size on inputs also stops iOS zooming on focus.
   --------------------------------------------------------------------- */
.field { margin-bottom: var(--sp-4); }

.field__label {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.field__hint {
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

.input, .select, .textarea {
  width: 100%;
  min-height: var(--tap-comfy);
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface-raised);
  border: var(--border-strong);
  border-radius: var(--radius);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
  transition: border-color var(--dur-fast) var(--ease);
}

.textarea { min-height: 96px; padding-top: var(--sp-3); resize: vertical; }

.input::placeholder, .textarea::placeholder { color: var(--c-text-muted); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--c-neon);
  box-shadow: var(--focus-ring);
}

/* ---------------------------------------------------------------------
   BOTTOM NAVIGATION
   Identical markup and position on every screen. It never moves.
   --------------------------------------------------------------------- */
.nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-nav);
  background: var(--c-bg-deep);
  border-top: var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.nav__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

.nav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-height: var(--nav-height);
  padding: var(--sp-2) var(--sp-1);
  color: var(--c-text-muted);
  text-decoration: none;
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  transition: color var(--dur-fast) var(--ease);
}

.nav__item:hover { color: var(--c-text-soft); }

.nav__icon {
  width: 24px;
  height: 24px;
  display: block;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Current tab. One indicator, no badge, nothing to dismiss. */
.nav__item[aria-current="page"] { color: var(--c-tab-current); }
.nav__item[aria-current="page"] .nav__label { font-weight: var(--fw-bold); }

/* ---------------------------------------------------------------------
   STATUS / EMPTY / ERROR CARDS
   A failed fetch renders one of these. Never a stack trace, never blank.
   --------------------------------------------------------------------- */
.notice {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}

.notice--warn  { border-color: var(--c-overdue-line); background: var(--c-overdue-wash); }
.notice--ok    { border-color: var(--c-primary);      background: var(--c-primary-wash); }
.notice--error { border-color: var(--c-danger);       background: var(--c-danger-wash); }

.notice__title { font-weight: var(--fw-bold); margin-bottom: var(--sp-1); }
.notice__text  { color: var(--c-text-soft); }

.empty {
  padding: var(--sp-10) var(--sp-4);
  text-align: center;
  color: var(--c-text-muted);
}
.empty__headline {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
  color: var(--c-text-soft);
  margin-bottom: var(--sp-2);
}

/* Quiet "last updated" line under cached calendar data. */
.stamp {
  margin-top: var(--sp-3);
  font-size: var(--fs-micro);
  color: var(--c-text-muted);
}

/* Placeholder marker on seeded-but-unconfirmed content. */
.tag-placeholder {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--c-overdue-wash);
  border: 1px solid var(--c-overdue-line);
  color: var(--c-overdue);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

/* ---------------------------------------------------------------------
   LOGIN
   --------------------------------------------------------------------- */
.login {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--sp-6) var(--gutter) calc(var(--sp-8) + env(safe-area-inset-bottom, 0px));
  max-width: 420px;
  margin: 0 auto;
  width: 100%;
}

.login__brand {
  text-align: center;
  margin-bottom: var(--sp-8);
}

.login__title {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h1);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-tight);
}
.login__title em {
  font-style: normal;
  color: var(--c-primary);
}

.login__tagline {
  margin-top: var(--sp-2);
  color: var(--c-text-muted);
  font-size: var(--fs-body);
}

/* Who are you: two large targets, nothing else on screen. */
.who {
  display: grid;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}

.who__btn {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: var(--tap-large);
  padding: var(--sp-4);
  background: var(--c-surface);
  border: var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--c-text);
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.who__btn:hover { background: var(--c-surface-raised); }
.who__btn[aria-pressed="true"] {
  border-color: var(--c-neon);
  background: var(--c-neon-wash);
}

.who__avatar {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  background: var(--c-primary);
  color: var(--c-text-on-light);
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
}

.who__role {
  display: block;
  font-size: var(--fs-small);
  font-weight: var(--fw-regular);
  color: var(--c-text-muted);
}

/* PIN entry. Large, numeric, one job. */
.pin-input {
  width: 100%;
  min-height: var(--tap-large);
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface-raised);
  border: 2px solid var(--c-line-strong);
  border-radius: var(--radius-lg);
  color: var(--c-text);
  font-family: var(--font-mono);
  font-size: var(--fs-h2);
  letter-spacing: 0.5em;
  text-align: center;
  text-indent: 0.5em; /* offsets the trailing letter-spacing so it looks centred */
}
.pin-input:focus {
  outline: none;
  border-color: var(--c-neon);
  box-shadow: var(--focus-ring);
}

.login__error {
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--c-danger);
  background: var(--c-danger-wash);
  color: var(--c-text);
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}

.login__foot {
  margin-top: var(--sp-6);
  text-align: center;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
}

/* The "not you?" link is secondary, but it is still something a person
   taps on a phone, so it gets the same 48px floor as everything else. */
.login__foot a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: 0 var(--sp-4);
  color: var(--c-text-soft);
}

/* ---------------------------------------------------------------------
   ACCOUNT STRIP (top of every signed-in screen)
   --------------------------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--sp-3) var(--gutter) 0;
  width: 100%;
}

.topbar__who {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

.topbar__dot {
  width: 10px; height: 10px;
  border-radius: var(--radius-pill);
  background: var(--c-primary);
}

.topbar__link {
  min-height: var(--tap-min);
  display: inline-flex;
  align-items: center;
  padding: 0 var(--sp-2);
  color: var(--c-text-muted);
  font-size: var(--fs-body);
  text-decoration: none;
}
.topbar__link:hover { color: var(--c-text); }

/* ---------------------------------------------------------------------
   PHASE STUB - removed once each screen is built
   --------------------------------------------------------------------- */
.stub {
  border: 1px dashed var(--c-line-strong);
  border-radius: var(--radius-lg);
  padding: var(--sp-8) var(--sp-4);
  text-align: center;
  color: var(--c-text-muted);
}
.stub__phase {
  display: inline-block;
  margin-bottom: var(--sp-3);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--c-primary-wash);
  border: 1px solid var(--c-primary);
  color: var(--c-primary-bright);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}
.stub__what {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
  color: var(--c-text-soft);
  margin-bottom: var(--sp-2);
}

/* ---------------------------------------------------------------------
   WIDER SCREENS
   The Chromebook gets more breathing room, not a different layout.
   Navigation stays exactly where it is.
   --------------------------------------------------------------------- */
@media (min-width: 700px) {
  :root { --gutter: var(--sp-6); }
  .app__main { padding-top: var(--sp-6); }
}

/* =====================================================================
   PHASE 2 - Today, week schedule and classes
   ===================================================================== */

/* ---------------------------------------------------------------------
   FLASH
   One line, self-dismissing, never a modal. Completing something should
   not cost a tap to acknowledge.
   --------------------------------------------------------------------- */
.flash {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface-raised);
  color: var(--c-text);
  animation: flash-in var(--dur-base) var(--ease-out);
}
.flash--done  { border-color: var(--c-done);    background: var(--c-done-wash); }
.flash--ok    { border-color: var(--c-primary); background: var(--c-primary-wash); }
.flash--error { border-color: var(--c-danger);  background: var(--c-danger-wash); }

@keyframes flash-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------
   DAY HEADER
   The biggest thing on the screen, because "what day is it" sits
   underneath most of the other questions.
   --------------------------------------------------------------------- */
.daybar { margin-bottom: var(--sp-5); }

.daybar__day {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-hero);
  line-height: 0.95;
  letter-spacing: var(--ls-display);
  color: var(--c-text);
}

.daybar__date {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-lead);
  color: var(--c-text-soft);
}

.daytype {
  display: inline-block;
  margin: var(--sp-3) 0 0;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-pill);
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-text-soft);
}
.daytype--mass    { border-color: var(--c-mass); color: var(--c-mass-text); background: var(--c-mass-wash); }
.daytype--pe      { border-color: var(--c-primary); color: var(--c-primary-bright); background: var(--c-primary-wash); }
.daytype--weekend { border-color: var(--c-line-strong); color: var(--c-text-muted); }

.daybar__note {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

/* ---------------------------------------------------------------------
   OVERDUE BAND
   Amber, not red. Clear but calm.
   --------------------------------------------------------------------- */
.band {
  margin-bottom: var(--sp-6);
  padding: var(--sp-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}
.band--overdue {
  border-color: var(--c-overdue-line);
  background: var(--c-overdue-wash);
}
.band__title {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-display);
  color: var(--c-overdue);
  margin-bottom: var(--sp-1);
}
.band__note {
  margin-bottom: var(--sp-3);
  font-size: var(--fs-body);
  color: var(--c-text-soft);
  line-height: var(--lh-snug);
}
.band .tasks { margin: 0; }

/* ---------------------------------------------------------------------
   TASK LIST
   --------------------------------------------------------------------- */
.tasks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.task {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--tap-large);
  padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-2);
  border-radius: var(--radius);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  overflow: hidden;
  transition: opacity var(--dur-base) var(--ease),
              transform var(--dur-base) var(--ease);
}

.task--overdue  { border-color: var(--c-overdue-line); background: var(--c-overdue-faint); }
.task--tomorrow { background: transparent; }

.task__form { margin: 0; flex: 0 0 auto; }

.task__stripe {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
}

.task__title {
  margin: 0;
  font-size: var(--fs-body-lg);
  line-height: var(--lh-snug);
  color: var(--c-text);
  overflow-wrap: anywhere;
}

.task__meta {
  margin-top: var(--sp-1);
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

.task__prio {
  display: inline-block;
  margin-right: var(--sp-2);
  padding: 0 var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--c-overdue-wash);
  color: var(--c-overdue);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
}

/* The tick control: 48px of target wrapped around a 26px circle. */
.check {
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: var(--radius-pill);
  -webkit-tap-highlight-color: transparent;
}
.check::before {
  content: "";
  grid-area: 1 / 1;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-pill);
  border: 2px solid var(--c-line-strong);
  background: transparent;
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              transform var(--dur-instant) var(--ease);
}
.check:hover::before  { border-color: var(--c-primary); }
.check:active::before { transform: scale(0.88); }

.check__tick {
  grid-area: 1 / 1;
  width: 18px; height: 18px;
  fill: none;
  stroke: var(--c-text-on-light);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transform: scale(0.5);
  transition: opacity var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease-out);
}

/* Completion: the tick lands, the circle fills, the row slides out.
   Fast and finished. No blocking modal, nothing to dismiss. */
.task.is-done .check::before { border-color: var(--c-done); background: var(--c-done); }
.task.is-done .check__tick   { opacity: 1; transform: scale(1); }
.task.is-done .task__title   { text-decoration: line-through; color: var(--c-text-muted); }
.task.is-leaving {
  opacity: 0;
  transform: translateX(12px);
}

/* ---------------------------------------------------------------------
   TIMELINE
   --------------------------------------------------------------------- */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

.tl {
  display: grid;
  grid-template-columns: 76px 20px minmax(0, 1fr);
  align-items: start;
  gap: var(--sp-2);
  padding: var(--sp-2) 0;
  min-height: var(--tap-min);
}

.tl__time {
  font-size: var(--fs-body);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-muted);
  padding-top: 2px;
  white-space: nowrap;
}

/* The connecting rail lives in the middle column so it lines up whatever
   height the row turns out to be. */
.tl__rail {
  position: relative;
  align-self: stretch;
  display: grid;
  justify-items: center;
}
.tl__rail::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--c-line);
}
.tl:first-child .tl__rail::before { top: 10px; }
.tl:last-child  .tl__rail::before { bottom: calc(100% - 12px); }

.tl__dot {
  position: relative;
  z-index: 1;
  width: 10px; height: 10px;
  margin-top: 6px;
  border-radius: var(--radius-pill);
  background: var(--dot, var(--c-line-strong));
  box-shadow: 0 0 0 3px var(--c-bg);
}

.tl__body {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  min-width: 0;
}

.tl__name {
  font-size: var(--fs-body);
  color: var(--c-text);
  overflow-wrap: anywhere;
}

.tl__sub {
  flex-basis: 100%;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
}

.tl--type-lunch .tl__name,
.tl--type-recess .tl__name,
.tl--type-dismissal .tl__name { color: var(--c-text-soft); }

/* ---------------------------------------------------------------------
   CALENDAR EVENTS
   --------------------------------------------------------------------- */
.events {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.event {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  padding: var(--sp-3);
  border-radius: var(--radius);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}

.event__dot {
  flex: 0 0 auto;
  width: 10px; height: 10px;
  margin-top: 7px;
  border-radius: var(--radius-pill);
}

.event__body { min-width: 0; }

.event__name {
  display: block;
  font-size: var(--fs-body);
  color: var(--c-text);
  overflow-wrap: anywhere;
}

.event__meta {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

/* ---------------------------------------------------------------------
   QUIET EMPTY STATE
   "Nothing due today" is good news. It should not look like an error or
   occupy an illustrated panel.
   --------------------------------------------------------------------- */
.quiet-empty {
  margin: 0;
  padding: var(--sp-3) 0;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
}

/* ---------------------------------------------------------------------
   QUICK ADD
   Pinned above the nav. One field, one button, and it is the only
   primary action on the Today screen.
   --------------------------------------------------------------------- */
.quickadd {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--nav-height) + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-sticky);
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--sp-2) var(--gutter);
  background: linear-gradient(to top, var(--c-bg) 72%, transparent);
}

.quickadd__input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--tap-comfy);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface-raised);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
}
.quickadd__input::placeholder { color: var(--c-text-muted); }
.quickadd__input:focus {
  outline: none;
  border-color: var(--c-neon);
  box-shadow: var(--focus-ring);
}

.quickadd__btn {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--tap-comfy);
  height: var(--tap-comfy);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--c-primary);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              transform var(--dur-instant) var(--ease);
}
.quickadd__btn:hover  { background: var(--c-primary-bright); }
.quickadd__btn:active { transform: scale(0.94); }
.quickadd__btn svg {
  width: 24px; height: 24px;
  fill: none;
  stroke: var(--c-text-on-light);
  stroke-width: 2.5;
  stroke-linecap: round;
}

/* ---------------------------------------------------------------------
   WEEK VIEW
   Phone: one day at a time, chosen with tabs. A five-column grid at
   375px would need either horizontal scrolling or unreadable text, and
   neither is acceptable.
   Wider screen: the whole week as a grid.
   --------------------------------------------------------------------- */
.daytabs {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--sp-1);
  margin-bottom: var(--sp-5);
  padding: var(--sp-1);
  border-radius: var(--radius);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
}

.daytab {
  display: grid;
  place-items: center;
  align-content: center;
  min-height: var(--tap-min);
  border-radius: var(--radius-sm);
  color: var(--c-text-muted);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  text-decoration: none;
}
.daytab:hover { background: var(--c-surface-raised); color: var(--c-text); }
.daytab[aria-current="page"] {
  background: var(--c-primary);
  color: var(--c-text-on-light);
  font-weight: var(--fw-bold);
}
.daytab__dot {
  width: 4px; height: 4px;
  margin-top: 3px;
  border-radius: var(--radius-pill);
  background: currentColor;
}

.weekgrid { display: none; }

@media (min-width: 760px) {
  .weekgrid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--sp-2);
    align-items: start;
  }

  .weekcol__head {
    padding: var(--sp-2) 0;
    font-family: var(--font-display);
    font-weight: var(--fw-display);
    font-size: var(--fs-body);
    letter-spacing: var(--ls-display);
    text-align: center;
    color: var(--c-text-soft);
  }
  .weekcol__head--today { color: var(--c-neon); }

  .weekcell {
    margin-bottom: var(--sp-2);
    padding: var(--sp-2);
    border-radius: var(--radius-sm);
    border: 1px solid var(--c-line);
    border-left: 3px solid var(--cell, var(--c-line-strong));
    background: var(--c-surface);
  }
  .weekcell__time {
    display: block;
    font-size: var(--fs-micro);
    font-variant-numeric: tabular-nums;
    color: var(--c-text-muted);
  }
  .weekcell__name {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-small);
    color: var(--c-text);
    overflow-wrap: anywhere;
  }
  .weekcell--break {
    background: transparent;
    border-left-color: var(--c-line);
  }
  .weekcell--break .weekcell__name { color: var(--c-text-muted); }
}

/* ---------------------------------------------------------------------
   CLASS CARDS AND GRADING CHART
   --------------------------------------------------------------------- */
.classcard {
  margin-bottom: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  border-top: 3px solid var(--accent, var(--c-primary));
  background: var(--c-surface);
}

.classcard__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}

.classcard__name {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-display);
  color: var(--c-text);
}

.classcard__teacher {
  margin: 0;
  font-size: var(--fs-body);
  color: var(--c-text-soft);
}

.classcard__meta {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

/* The teacher's email is a real tap target, so it gets the 48px floor even
   though it sits inline in a metadata line. */
.classcard__mail {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  font-size: var(--fs-body);
  color: var(--c-primary-bright);
  overflow-wrap: anywhere;
}

.classcard__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  margin-top: var(--sp-3);
  padding: 0 var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--c-line-strong);
  color: var(--c-text);
  text-decoration: none;
  font-size: var(--fs-body);
}
.classcard__link:hover { background: var(--c-surface-raised); }

.classcard__notes {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-line);
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  line-height: var(--lh-body);
}

/* The grading breakdown: one labelled bar per category, and every
   percentage followed by a sentence saying what it means. */
.grading { margin-top: var(--sp-4); }

.grading__title {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.gradebar { margin-bottom: var(--sp-4); }
.gradebar:last-child { margin-bottom: 0; }

.gradebar__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}

.gradebar__cat {
  font-size: var(--fs-body);
  color: var(--c-text);
}

.gradebar__pct {
  font-size: var(--fs-body);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  /* Always raspberry: the class colours are bright decoration now and
     cannot be trusted as text colours. The bar itself carries the class
     colour; the number carries the contrast. */
  color: var(--c-primary);
}

.gradebar__track {
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--c-track);
  overflow: hidden;
}

.gradebar__fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--accent, var(--c-primary));
}

.gradebar__note {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

.grading__summary {
  margin-top: var(--sp-4);
  padding: var(--sp-3);
  border-radius: var(--radius);
  background: var(--c-surface-raised);
  font-size: var(--fs-body);
  color: var(--c-text-soft);
  line-height: var(--lh-body);
}

.grading__none {
  margin-top: var(--sp-3);
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

/* Grade scale reference. */
.scale {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(58px, 1fr));
  gap: var(--sp-2);
  margin: var(--sp-3) 0;
}
.scale__band {
  padding: var(--sp-2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--c-line);
  background: var(--c-surface-raised);
  text-align: center;
}
.scale__letter {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
  color: var(--c-text);
}
.scale__range {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-muted);
}

.policy dt {
  margin-top: var(--sp-3);
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}
.policy dd {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-body);
  color: var(--c-text-soft);
  line-height: var(--lh-body);
}

/* =====================================================================
   SCHEDULE - Day / Week / Month
   ===================================================================== */

/* Three-way view switcher, built on the daytabs base. */
.daytabs--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* One-line heads-up under a heading: "Tomorrow is a P.E. day." */
.prep-note {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  font-size: var(--fs-body);
  color: var(--c-text-soft);
  line-height: var(--lh-snug);
}

/* ---------------------------------------------------------------------
   DATE / MONTH NAVIGATION
   Two large arrows and a label. The arrows are the only controls.
   --------------------------------------------------------------------- */
.datenav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.datenav__arrow {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--tap-comfy);
  height: var(--tap-comfy);
  border-radius: var(--radius);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-text-soft);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.datenav__arrow:hover { background: var(--c-surface-raised); color: var(--c-text); }
.datenav__arrow svg {
  width: 22px; height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.datenav__label { text-align: center; min-width: 0; }
.datenav__day {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h3);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-tight);
}
.datenav__date {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
}

.datenav__back {
  margin: calc(-1 * var(--sp-2)) 0 var(--sp-3);
  text-align: center;
}
.datenav__back a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 0 var(--sp-4);
  font-size: var(--fs-body);
  color: var(--c-primary-bright);
  text-decoration: none;
}

/* ---------------------------------------------------------------------
   WEEK - phone: the five days stacked
   --------------------------------------------------------------------- */
.weekstack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.wday {
  padding: var(--sp-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}
.wday--today { border-color: var(--c-primary); }

.wday__name {
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-lead);
  letter-spacing: var(--ls-display);
  margin-bottom: var(--sp-3);
}
.wday__now {
  display: inline-block;
  vertical-align: middle;
  margin-left: var(--sp-2);
  padding: 0 var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--c-primary-wash);
  border: 1px solid var(--c-primary);
  color: var(--c-primary-bright);
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.wrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-1) 0;
  min-height: 32px;
}
.wrow__time {
  flex: 0 0 76px;
  font-size: var(--fs-body);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-muted);
  white-space: nowrap;
}
.wrow__dot {
  flex: 0 0 auto;
  width: 8px; height: 8px;
  border-radius: var(--radius-pill);
  background: var(--c-line-strong);
}
.wrow__name {
  min-width: 0;
  font-size: var(--fs-body);
  color: var(--c-text);
  overflow-wrap: anywhere;
}
.wrow--break .wrow__name { color: var(--c-text-muted); }
.wrow--break .wrow__dot  { background: var(--c-line); }

/* On the wide layout, the stacked cards give way to the grid. */
@media (min-width: 760px) {
  .weekstack { display: none; }
}

/* ---------------------------------------------------------------------
   MONTH GRID
   Dots per event on a phone; short titles appear at desktop width.
   Every cell is a link to that day's Day view, so the detail is always
   one tap away rather than crammed into the cell.
   --------------------------------------------------------------------- */
.month {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--sp-1);
}

.month__dow {
  padding: var(--sp-2) 0;
  text-align: center;
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-text-muted);
}

.mcell {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-height: var(--tap-comfy);
  padding: var(--sp-1);
  border-radius: var(--radius-sm);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.mcell:hover { background: var(--c-surface-raised); border-color: var(--c-line-strong); }

.mcell--out { background: transparent; }
.mcell--out .mcell__n { color: var(--c-text-muted); opacity: 0.55; }

.mcell--today { border-color: var(--c-neon); }
.mcell--today .mcell__n { color: var(--c-neon); font-weight: var(--fw-bold); }

.mcell__n {
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-soft);
  line-height: 1;
}

.mdots {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  align-items: center;
}
.mdot {
  width: 7px; height: 7px;
  border-radius: var(--radius-pill);
}
.mdot--more {
  width: auto; height: auto;
  border-radius: 0;
  background: none;
  color: var(--c-text-muted);
  font-size: var(--fs-micro);
  line-height: 1;
}

/* Short event titles: hidden on a phone, shown on the Chromebook where
   the cells are big enough to carry them. */
.mcell__list { display: none; }

@media (min-width: 760px) {
  .mcell { min-height: 92px; padding: var(--sp-2); }
  .mdots { display: none; }
  .mcell__list {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
  }
  .mcell__evt {
    font-size: var(--fs-micro);
    line-height: var(--lh-snug);
    color: var(--c-text-soft);
    border-left: 3px solid var(--c-line-strong);
    padding-left: var(--sp-1);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .mcell__more {
    font-size: var(--fs-micro);
    color: var(--c-text-muted);
  }
}

/* =====================================================================
   PHASE 3 - task management
   ===================================================================== */

/* Four-way view switcher, same component as the schedule's. */
.daytabs--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ---------------------------------------------------------------------
   TASK ROW - edit link and done state
   The row body is a link to the edit screen; the circle stays a button.
   --------------------------------------------------------------------- */
.task__link {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}

.task__body { min-width: 0; flex: 1 1 auto; display: block; }

.task__title { display: block; }
.task__meta  { display: block; }

.task__chev {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  fill: none;
  stroke: var(--c-text-muted);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.7;
}

/* Done rows: quiet, struck through, circle filled. Tapping the circle
   puts the task back - the mis-tap undo. */
.task--done .task__title {
  text-decoration: line-through;
  color: var(--c-text-muted);
}
.task--done .check::before {
  border-color: var(--c-done);
  background: var(--c-done);
}
.task--done .check__tick { opacity: 1; transform: scale(1); }
.task--done .check:hover::before { border-color: var(--c-text-muted); background: transparent; }
.task--done .check:hover .check__tick { opacity: 0.4; }

/* Repeating-definition rows get the loop mark where the circle would be. */
.task__repeat {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
}
.task__repeat svg {
  width: 22px; height: 22px;
  fill: none;
  stroke: var(--c-text-muted);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------------------------------------------------------------------
   FORM CONTROLS - pills and weekday picker
   Real radios and checkboxes underneath, so keyboard and no-JS work.
   --------------------------------------------------------------------- */
.field--bare {
  border: 0;
  padding: 0;
  margin: 0 0 var(--sp-4);
}
.field--bare legend { padding: 0; }

.pills {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

.pill { position: relative; }

.pill input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}

.pill__face {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: 0 var(--sp-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-text-soft);
  font-size: var(--fs-body);
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}

.pill input:checked + .pill__face {
  background: var(--c-primary-wash);
  border-color: var(--c-primary);
  color: var(--c-primary-bright);
  font-weight: var(--fw-bold);
}
.pill input:checked + .pill__face--high {
  background: var(--c-overdue-wash);
  border-color: var(--c-overdue);
  color: var(--c-overdue);
}
.pill input:focus-visible + .pill__face {
  box-shadow: var(--focus-ring);
}

.weekdays {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-3);
}

.wd { position: relative; }

.wd input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}

.wd__face {
  display: grid;
  place-items: center;
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  padding: 0 var(--sp-2);
  border-radius: var(--radius);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-text-soft);
  font-size: var(--fs-body);
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.wd input:checked + .wd__face {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-text-on-light);
  font-weight: var(--fw-bold);
}
.wd input:focus-visible + .wd__face {
  box-shadow: var(--focus-ring);
}

/* ---------------------------------------------------------------------
   FORM FOOT AND THE DELETE AREA
   Save is the only loud thing on the screen. Delete starts quiet and
   only turns red on the armed confirm step.
   --------------------------------------------------------------------- */
.form-foot {
  display: grid;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
}

.danger {
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--c-line);
}

.btn--danger {
  background: var(--c-danger);
  border-color: var(--c-danger);
  color: var(--c-text-on-light);
  font-weight: var(--fw-bold);
}
.btn--danger:hover { background: #F68B93; border-color: #F68B93; }

/* =====================================================================
   PHASE 4 - calendar feeds
   ===================================================================== */

/* ---------------------------------------------------------------------
   MONTH LEGEND
   One chip per calendar; tapping toggles that feed. An off chip stays
   visible and readable so what is hidden is never a mystery.
   --------------------------------------------------------------------- */
.feedlegend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

.feedchip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap-min);
  padding: 0 var(--sp-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface);
  color: var(--c-text);
  font-size: var(--fs-body);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease),
              opacity var(--dur-fast) var(--ease);
}
.feedchip:hover { background: var(--c-surface-raised); }

.feedchip__dot {
  width: 10px; height: 10px;
  border-radius: var(--radius-pill);
  flex: 0 0 auto;
}

.feedchip--off {
  opacity: 0.5;
  border-style: dashed;
  color: var(--c-text-muted);
}
.feedchip--off .feedchip__dot { opacity: 0.4; }

/* ---------------------------------------------------------------------
   FEED ROWS in Settings
   --------------------------------------------------------------------- */
.feedrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-2);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}
.feedrow--off { opacity: 0.6; }

.feedrow__dot {
  flex: 0 0 auto;
  width: 12px; height: 12px;
  border-radius: var(--radius-pill);
}

.feedrow__body { flex: 1 1 auto; min-width: 0; }

.feedrow__name {
  margin: 0;
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  color: var(--c-text);
}

.feedrow__status {
  margin: 2px 0 0;
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}
.feedrow__status--ok   { color: var(--c-text-soft); }
.feedrow__status--warn { color: var(--c-overdue); }

.feedrow__error {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}

.feedrow__toggle { margin: 0; flex: 0 0 auto; }

/* =====================================================================
   PHASE 5 - links hub
   ===================================================================== */

/* ---------------------------------------------------------------------
   SEARCH
   --------------------------------------------------------------------- */
.searchbar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
}

.searchbar__input { flex: 1 1 auto; border-radius: var(--radius-pill); }

.searchbar__clear {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 0 var(--sp-3);
  color: var(--c-text-muted);
  font-size: var(--fs-body);
  text-decoration: none;
}
.searchbar__clear:hover { color: var(--c-text); }

/* ---------------------------------------------------------------------
   CARD GRID - student mode
   Two columns from about 360px up; the whole card is the tap target.
   --------------------------------------------------------------------- */
.resgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--sp-3);
}

.rescard {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-height: var(--tap-large);
  padding: var(--sp-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  color: var(--c-text);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              transform var(--dur-instant) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.rescard:hover  { background: var(--c-surface-raised); border-color: var(--c-line-strong); }
.rescard:active { transform: scale(0.98); }

.rescard__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-2);
}

.rescard__name {
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.rescard__out {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  margin-top: 2px;
  fill: none;
  stroke: var(--c-primary-bright);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rescard__desc {
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  line-height: var(--lh-snug);
}

/* ---------------------------------------------------------------------
   MANAGE MODE - parent rows
   --------------------------------------------------------------------- */
.manrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-2);
  border-radius: var(--radius-lg);
  border: 1px solid var(--c-line);
  background: var(--c-surface);
}
.manrow--archived { opacity: 0.65; }

.manrow__body { flex: 1 1 auto; min-width: 0; }

.manrow__name {
  margin: 0;
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  color: var(--c-text);
  overflow-wrap: anywhere;
}

.manrow__url {
  margin: 2px 0 0;
  font-size: var(--fs-small);
  font-family: var(--font-mono);
  color: var(--c-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.manrow__tools {
  flex: 0 0 auto;
  display: flex;
  gap: var(--sp-1);
}
.manrow__tools form { margin: 0; }

.manrow__btn {
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius);
  background: var(--c-surface-raised);
  color: var(--c-text-soft);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease);
}
.manrow__btn:hover { background: var(--c-surface-hover); color: var(--c-text); }
.manrow__btn[disabled] { opacity: 0.35; cursor: default; }
.manrow__btn svg {
  width: 20px; height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------------------------------------------------------------------
   CHECKBOX LINE on the form
   --------------------------------------------------------------------- */
.checkline {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  min-height: var(--tap-min);
  cursor: pointer;
  font-size: var(--fs-body);
  color: var(--c-text-soft);
  line-height: var(--lh-snug);
  padding: var(--sp-2) 0;
}

.checkline input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
}

.checkline__face {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  margin-top: 1px;
  border-radius: var(--radius-sm);
  border: 2px solid var(--c-line-strong);
  background: transparent;
  display: grid;
  place-items: center;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.checkline__face::after {
  content: "";
  width: 12px; height: 7px;
  border-left: 3px solid var(--c-text-on-light);
  border-bottom: 3px solid var(--c-text-on-light);
  transform: rotate(-45deg) translateY(-1px);
  opacity: 0;
}
.checkline input:checked + .checkline__face {
  background: var(--c-primary);
  border-color: var(--c-primary);
}
.checkline input:checked + .checkline__face::after { opacity: 1; }
.checkline input:focus-visible + .checkline__face { box-shadow: var(--focus-ring); }

/* Admin form bits: colour well, grading rows, time pair. */
.colorwell {
  width: 100%;
  min-height: var(--tap-comfy);
  padding: var(--sp-1);
  background: var(--c-surface-raised);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius);
  cursor: pointer;
}

.graderow {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) 74px minmax(0, 2fr);
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
@media (max-width: 560px) {
  .graderow { grid-template-columns: minmax(0, 1fr) 74px; }
  .graderow__note { grid-column: 1 / -1; }
}

.timerow {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}


/* =====================================================================
   COLLAPSIBLE CLASS CARDS
   Native details/summary: works with no JavaScript, keyboard included.
   Collapsed, the Classes page is a scannable list of name + teacher;
   one tap opens the grading chart and notes for just that class.
   ===================================================================== */

.classcard > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--tap-min);
  -webkit-tap-highlight-color: transparent;
}
.classcard > summary::-webkit-details-marker { display: none; }

.classcard__sumtext { min-width: 0; }

.classcard__chev {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  fill: none;
  stroke: var(--c-text-muted);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur-fast) var(--ease);
}
.classcard[open] > summary .classcard__chev { transform: rotate(180deg); }

.classcard__body {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-line);
}

.classcard > summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}
