/* The office app: sidebar shell, login screen, and the dense screens staff
   live in all day.

   Same shell as the kindergarten build - deep teal sidebar with one crayon
   colour per section, sticky topbar, content column - with the sidebar in
   grid/flex order 1, which RTL puts on the right with no mirroring rule. */

/* ======================================================================
   login
   ====================================================================== */

/* A photograph behind the gradient layers, as in the kindergarten build.

   LAYER ORDER MATTERS, and not in the obvious way. CSS paints the first
   background-image on top, so the teal scrim is listed first and the two
   crayon radials sit UNDER it. Put the radials on top - which is what the
   gradient-only version did, and what copying it verbatim gives you - and
   they lighten the composite over the photo's blown-out highlights: white
   text measured 3.12:1 that way, against 6.42:1 with the scrim on top. The
   radials still tint the image from underneath; the teal alone decides how
   bright the result is allowed to get.

   The image is served at two sizes (1600px and 800px) off a media query, not
   as one large file: the original was 5824px and 9.2 MB, which is a minute of
   a metered Balkh connection to look at a login screen. See public/img/. */
.login-page {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  position: relative;
  /* The card's accent, in three shades, because one violet cannot do all
     three jobs on glass this translucent. Same pairing rule as the --x /
     --x-ink tokens the rest of the app already uses. */
  --login-accent: #cfcefe;
  --login-accent-soft: #e2e1ff;  /* the focus border: 7.76:1, and a graphic needs 3 */
  --login-accent-text: #e2e1ff;  /* the floating label and the link: 10.10:1 */
  background-color: #232a3a;
  background-image:
    linear-gradient(160deg, rgba(35, 42, 58, 0.73) 0%, rgba(52, 62, 86, 0.65) 55%, rgba(52, 62, 86, 0.71) 100%),
    radial-gradient(circle at 15% 20%, rgba(250, 226, 122, 0.3) 0, transparent 42%),
    radial-gradient(circle at 85% 80%, rgba(207, 206, 254, 0.36) 0, transparent 46%),
    url('/img/login-bg.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

@media (max-width: 900px) {
  .login-page { background-image:
    linear-gradient(160deg, rgba(35, 42, 58, 0.73) 0%, rgba(52, 62, 86, 0.65) 55%, rgba(52, 62, 86, 0.71) 100%),
    radial-gradient(circle at 15% 20%, rgba(250, 226, 122, 0.3) 0, transparent 42%),
    radial-gradient(circle at 85% 80%, rgba(207, 206, 254, 0.36) 0, transparent 46%),
    url('/img/login-bg-sm.jpg');
  }
}

/* A glass panel floating on the photograph, rather than the opaque card the
   rest of the app uses.

   It is dark glass in BOTH themes, like the portal masthead. The ground here
   is a fixed photograph, so a card that flipped to light in light mode would
   be reading against the same dark image either way - the theme toggle on
   this screen is setting the preference for the app behind it, not restyling
   the door. */
.login-card {
  position: relative;
  width: 100%;
  max-width: 430px;
  padding: 34px 32px;
  border-radius: 28px;
  background: rgba(17, 28, 30, 0.42);
  border: 1px solid rgba(255, 255, 255, 0.16);
  /* saturate() keeps the photograph's colour alive through the blur; without
     it the glass turns everything behind it grey. */
  backdrop-filter: blur(22px) saturate(1.3);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.14);
  color: #fff;
}

/* Safari on older iOS, and Firefox with backdrop-filter disabled, render the
   card fully transparent - the text would sit straight on the photo. Solid
   fallback first, glass only where it is supported. */
@supports not (backdrop-filter: blur(2px)) {
  .login-card { background: rgba(13, 24, 26, 0.9); }
}

.login-card .mark {
  display: flex;
  justify-content: center;
  margin-block-end: 14px;
}
.login-card .mark img { width: 52px; height: 52px; }
.login-card h1 {
  font-family: var(--font-display);
  font-size: clamp(26px, 6vw, 33px);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: #fff;
  margin-block-end: 6px;
}
.login-card .sub {
  text-align: center;
  color: rgba(255, 255, 255, 0.66);
  font-size: var(--fs-base);
  margin-block-end: 22px;
}

/* --- the sign-in card's version of the outlined field -------------------

   The field itself now lives in app.css and is used by every screen. What is
   left here is only what this card does differently, and it is scoped to
   .login-card ON PURPOSE.

   These rules were unscoped for one revision, and the cost was immediate: the
   floated label's hardcoded rgba(255,255,255,.72) leaked out of the login
   screen and turned every label in the app white, which on the light theme's
   white cards is invisible. The card is dark glass in both themes, so it
   cannot read the --field-* tokens; it has to restate them, and it has to
   stay behind a selector while it does. */
.login-card .gfield { margin-block-end: 16px; }
.login-card .gfield > input { color: #fff; }
/* See the note in app.css: an inset shadow here painted a solid slab behind
   an autofilled field while every other field stayed see-through. */
.login-card .gfield > input:-webkit-autofill, .login-card .gfield > input:-webkit-autofill:focus {
  -webkit-text-fill-color: #fff;
  transition: background-color 100000s ease-in-out 0s;
  caret-color: #fff;
}
@media (hover: hover) and (pointer: fine) { .login-card .gfield > input:-webkit-autofill:hover {
  -webkit-text-fill-color: #fff;
  transition: background-color 100000s ease-in-out 0s;
  caret-color: #fff;
} }
.login-card .gfield__outline { border-color: rgba(255, 255, 255, 0.22); }
.login-card .gfield__label { color: rgba(255, 255, 255, 0.6); }
.login-card .gfield > input:focus ~ .gfield__label,
.login-card .gfield > input:not(:placeholder-shown) ~ .gfield__label {
  color: rgba(255, 255, 255, 0.72);
}
.login-card .gfield > input:focus ~ .gfield__label { color: var(--login-accent-text); }
.login-card .gfield > input:focus ~ .gfield__outline {
  border-color: var(--login-accent-soft);
}
@media (hover: hover) and (pointer: fine) { .login-card .gfield:hover .gfield__outline { border-color: rgba(255, 255, 255, 0.34); } }

/* The label sits vertically centred in the field and horizontally on the
   reading edge - left in English, right in Pashto and Dari, which is what
   inset-inline-start resolves to. It is the app's default, inherited from
   app.css; nothing here overrides it. */

/* The eye toggle sits inside the field, so the input needs room for it. */
.login-card .gfield--reveal > input { padding-inline-end: 52px; }
.gfield__reveal {
  position: absolute;
  inset-inline-end: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: rgba(255, 255, 255, 0.62);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .gfield__reveal:hover { color: #fff; background: rgba(255, 255, 255, 0.1); } }
.gfield__reveal svg { width: 20px; height: 20px; display: block; }

/* The legend lowers the visible outline by half its line height. Center the
   custom control within that outline, and suppress the browser's second eye. */
.gfield--reveal .gfield__outline legend { line-height: 16px; }
.gfield--reveal .gfield__reveal {
  top: calc(50% + 4px);
  padding: 0;
  margin: 0;
  min-width: 40px;
  min-height: 40px;
  line-height: 1;
}
.gfield--reveal > input::-ms-reveal,
.gfield--reveal > input::-ms-clear { display: none; }
.gfield--reveal > input::-webkit-credentials-auto-fill-button { visibility: hidden; display: none !important; pointer-events: none; }

/* --- the rest of the card ---------------------------------------------- */

.login-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-block: -2px 18px;
}
.login-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 650;
  color: var(--login-accent-text);
  cursor: pointer;
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { .login-link:hover { text-decoration: underline; } }

.btn--login {
  width: 100%;
  min-height: 54px;
  border: none;
  border-radius: 14px;
  font-size: 16.5px;
  font-weight: 700;
  color: #20222a;
  background: linear-gradient(135deg, #e2e1ff 0%, #cfcefe 100%);
  box-shadow: 0 8px 22px rgba(85, 81, 255, 0.4);
}
@media (hover: hover) and (pointer: fine) { .btn--login:hover:not(:disabled) {
  background: linear-gradient(135deg, #ecebff 0%, #cfcefe 100%);
  box-shadow: 0 10px 26px rgba(85, 81, 255, 0.48);
} }
.btn--login:disabled { opacity: 0.6; }

/* A rule with the word sitting in a gap in it. */
.login-or {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-block: 20px 16px;
  color: rgba(255, 255, 255, 0.55);
  font-size: 13.5px;
}
.login-or::before,
.login-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(255, 255, 255, 0.18);
}

.btn--glass {
  width: 100%;
  min-height: 50px;
  border-radius: 14px;
  border: 1.5px solid rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  font-weight: 650;
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { .btn--glass:hover {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  text-decoration: none;
} }

.login-foot {
  margin-block-start: 18px;
  text-align: center;
  font-size: 13.5px;
  color: rgba(255, 255, 255, 0.6);
}

/* The language and theme controls, on the glass rather than on a white card. */
.login-card .segmented label {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.8);
}
.login-card .segmented input:checked + label {
  background: #fff;
  border-color: #fff;
  color: #20222a;
}
.login-card .label { color: rgba(255, 255, 255, 0.6); }
.login-card .segmented { flex: 1; }

/* On a 375px card the three language chips plus the theme button come to
   about 316px against 311px of room, so the theme button dropped onto a line
   of its own and sat there looking orphaned. Losing the radio dot - the
   selected chip is already a solid white pill, so the dot was saying it
   twice - buys back more than enough. */
@media (max-width: 460px) {
  .login-card .segmented label {
    padding: 9px 8px;
    font-size: 14px;
    gap: 0;
  }
  .login-card .segmented label::before { display: none; }
}
.login-card .icon-btn {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.2);
  color: #fff;
}
@media (hover: hover) and (pointer: fine) { .login-card .icon-btn:hover { background: rgba(255, 255, 255, 0.16); } }
.login-card .alert--error {
  background: rgba(120, 20, 30, 0.5);
  border-color: rgba(255, 140, 150, 0.5);
  color: #ffd0d6;
}
/* The forced password change shares this card, and the shared alert uses a
   dark ink meant for a white panel. */
.login-card .alert--warn {
  background: rgba(120, 82, 12, 0.5);
  border-color: rgba(247, 197, 106, 0.5);
  color: #fae27a;
}

/* ======================================================================
   shell
   ====================================================================== */

.app {
  display: flex;
  min-height: 100dvh;
}

.nav {
  position: relative;
  width: 252px;
  flex-shrink: 0;
  background: var(--teal-deep);
  background-image: radial-gradient(circle at 20% 15%, rgba(255, 255, 255, 0.05) 0, transparent 45%);
  color: #e8eaf0;
  padding: 16px 15px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  /* Pinned to the viewport, NOT stretched to the document.

     As a plain flex item the sidebar takes the height of the whole page, so
     on Students - 2799px of roll - it was 2799px tall and everything the
     .nav__foot auto-margin pushes to "the bottom" landed at 2734px, i.e. a
     full page-scroll away. That is why the language switcher was there on
     Dashboard and missing on Students: the pages that fit the viewport
     happened to work.

     Fixing the height also fixes the navigation itself, which used to scroll
     off the top of a long list and force a scroll back up to change section. */
  position: sticky;
  top: 0;
  height: 100dvh;
}

.nav__brand {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 4px 8px 14px;
  color: #fff;
}
/* 38px, not the .avatar default of 44: it puts the avatar's centre on the
   same 39px line as every icon below it, so nothing shifts sideways when the
   rail opens. */
.nav__avatar {
  width: 38px;
  height: 38px;
  font-size: 14px;
  flex: none;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}
/* The role sits ABOVE the name and small, as in the reference: you read who
   you are as a job first and a person second, which is the useful order when
   the question is "am I allowed to do this". */
.nav__role {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #a2a8b6;
  line-height: 1.2;
}
.nav__name {
  font-family: var(--font-display);
  font-weight: 650;
  font-size: 16px;
  line-height: 1.3;
  color: #fff;
}

.nav__divider {
  height: 1px;
  background: rgba(255, 255, 255, 0.13);
  margin-block: 0 12px;
  flex: none;
}

.nav__group + .nav__group { margin-block-start: 14px; }

/* The auto margin is what pins this to the bottom of the sidebar; .nav is
   already a flex column. Padding-block-end keeps it clear of a phone's home
   indicator when the drawer is full height.

   This only lands somewhere useful because .nav is viewport-height rather
   than document-height - see the note there. */
.nav__foot {
  margin-block-start: auto;
  padding: 14px 13px 13px;
  margin-block-end: 4px;
  /* A panel at the foot rather than loose controls, which is what the
     reference does with its bottom block. */
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--r);
}
.nav__foot .nav__label { padding-inline: 2px; }

/* The switcher was styled for the light appbar it used to sit in. On the deep
   teal it needs its own surface treatment: translucent white rather than
   --surface, which here would be a bright card floating in the sidebar. */
.langswitch--nav {
  border-color: rgba(255, 255, 255, 0.22);
  width: 100%;
}
.langswitch--nav button {
  flex: 1;
  background: rgba(255, 255, 255, 0.08);
  color: #e8eaf0;
  padding-inline: 8px;
  font-size: 13.5px;
}
@media (hover: hover) and (pointer: fine) { .langswitch--nav button:hover { background: rgba(255, 255, 255, 0.16); } }
/* 8.9:1 on the teal-deep sidebar. The shared rule's --secondary would be the
   same teal the sidebar already is, which would erase the selected state. */
.langswitch--nav button[aria-pressed='true'] {
  background: #fff;
  color: var(--teal-deep);
}
.nav__label {
  padding-inline: 10px;
  margin-block-end: 4px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #a2a8b6;
}

.nav a {
  display: flex;
  align-items: center;
  gap: 12px;
  /* 7 + 7 + the 30px tile = 44px, which is the touch floor exactly, and with
     the 6px gap below gives the 50px item pitch measured off the reference
     crop. The template's own pill is 39px, which is under the floor - this
     is the nearest height that keeps the rhythm without going under it, and
     it buys the foot card another 4px a row inside an 860px window. */
  padding: 7px 13px;
  border-radius: var(--r-sm);
  color: #dadde6;
  text-decoration: none;
  font-size: var(--fs-base);
  font-weight: 650;
}
@media (hover: hover) and (pointer: fine) { .nav a:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  text-decoration: none;
} }
.nav a[aria-current='page'] {
  background: rgba(255, 255, 255, 0.13);
  color: #fff;
}

/* The glyph's box. 30px wide with a 21px drawing inside it: the box is what
   holds an icon's centre on the 39px line the collapsed rail is built
   around, and the drawing is what you actually see. Icons inherit the row's
   colour rather than pinning their own, which is what lets one rule tint the
   whole column per theme. */
.nav__icon {
  width: 30px;
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}
.nav__icon svg { display: block; }

/* Same reason: a white glyph on marigold is under the 3:1 floor for a
   graphic, so this circle gets the dark ink. */
/* Teal on the teal sidebar would disappear - a hairline keeps it readable.
   Deliberately a border, not a box-shadow, so it cannot fight the active
   ring above. */

.main-col {
  flex: 1;
  /* min-width: 0 is what stops the mark grid from pushing the whole shell
     wider than the viewport. */
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.appbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 26px 10px;
  /* The page ground, not transparent. The bar is sticky, and a see-through
     sticky bar leaves the title and the controls sitting on top of whatever
     scrolls under them - every long list in the app did this. */
  background: var(--bg);
  border-block-end: none;
  position: sticky;
  top: 0;
  z-index: 5;
  flex-wrap: wrap;
  row-gap: 10px;
}
.appbar__left {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
.appbar__title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 650;
}
.appbar__right {
  display: flex;
  align-items: center;
  gap: 11px;
  flex-wrap: wrap;
}
.appbar select {
  width: auto;
  padding: 8px 12px;
  padding-inline-end: 32px;
  font-size: 14.5px;
  font-weight: 650;
}

.main { padding: 8px 26px 26px; flex: 1; min-width: 0; }

.menu-toggle { display: none; }
.nav-backdrop { display: none; }

/* --- page furniture --------------------------------------------------- */

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-block-end: 18px;
}
.page-head h1 { font-size: var(--fs-lg); margin: 0; }
.page-head__sub { color: var(--fg-muted); font-size: var(--fs-sm); }

.toolbar {
  display: flex;
  gap: 11px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-block-end: 17px;
}
.toolbar .field { margin: 0; min-width: 170px; }
.toolbar .field--wide { flex: 1 1 260px; }

/* ======================================================================
   dashboard: cubby stat cards
   ====================================================================== */

/* The peg-and-cubby motif from the kindergarten build. It survives the move
   to a high school because it is doing a real job: the peg colour is the
   section colour, so a tile and its sidebar entry match at a glance. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 22px 15px;
}
/* No peg. The dot that used to sit on a tile's top edge was drawn for a
   bordered card: it read as a pin holding the card to the page. On a card
   that floats on a shadow it reads as a bubble stuck above it, and the
   design this now follows marks a card with its heading, not with a dot. */
.tile {
  background: var(--surface);
  border: none;
  border-radius: var(--r);
  box-shadow: var(--panel-shadow);
  padding: 22px 18px 18px;
  position: relative;
}
/* This rule lost its own selector in an earlier sweep: what was left read
   `[dir='rtl'] .tile::before, [dir='rtl'] .tile__label`, so a tile label was
   styled in Pashto and Dari and left raw in English, where the app is LTR.
   The ::before it was flipping was the peg, which no longer exists. */
.tile__label {
  font-size: 13.5px;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 650;
  margin-block-end: 6px;
}
.tile__value {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.tile__meta { font-size: 13px; color: var(--fg-muted); margin-block-start: 4px; }

.tile--warn { border-color: var(--marigold); background: var(--marigold-soft); }
.tile--warn .tile__value { color: var(--warning-ink); }
.tile--ok { border-color: var(--grass); background: var(--grass-soft); }
.tile--ok .tile__value { color: var(--success); }
.tile--danger { border-color: var(--coral); background: var(--danger-soft); }
.tile--danger .tile__value { color: var(--danger); }

/* Progress bars use the kindergarten's wooden-block treatment: a repeating
   highlight and an inset shadow so a bar reads as a stack of blocks. */
.progress {
  height: 20px;
  border-radius: 7px;
  background: var(--surface-alt);
  overflow: hidden;
}
.progress__bar {
  height: 100%;
  min-width: 20px;
  border-radius: 7px;
  background-color: var(--teal);
  background-image: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.24) 0 3px, transparent 3px 27px);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.13);
  transition: width 0.5s ease;
}
.progress__bar--fail { background-color: var(--berry); }

/* ======================================================================
   mark entry grid
   ====================================================================== */

/* The densest screen in the app: 40 students down, 10 subjects across. The
   student column stays pinned while the subjects scroll sideways, because
   typing a mark into the wrong row is the failure this screen must prevent. */
.markgrid {
  max-height: 70vh;
  overflow: auto;
}
.markgrid table {
  border-collapse: separate;
  border-spacing: 0;
}
.markgrid thead th { position: sticky; top: 0; z-index: 3; }
.markgrid th.sticky-name,
.markgrid td.sticky-name {
  position: sticky;
  inset-inline-start: 0;
  z-index: 2;
  background: var(--surface);
  border-inline-end: 1px solid var(--border);
  min-width: 12rem;
}
.markgrid thead th.sticky-name { z-index: 4; background: var(--surface-alt); }
@media (hover: hover) and (pointer: fine) { .markgrid tbody tr:hover td.sticky-name { background: var(--surface-alt); } }
.markgrid tbody td { border-block-end: 1px solid var(--border); }

.markgrid input[type='text'] {
  width: 4.4rem;
  padding: 6px 8px;
  text-align: center;
  font-size: 15px;
}
/* Out-of-range marks are flagged as they are typed, not on save - by save
   time the typist has moved on and no longer knows which cell was wrong. */
.markgrid input.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-soft);
}
.markgrid input:disabled { background: var(--surface-alt); border-style: dashed; }
.markgrid td.absent-cell input { opacity: 0.35; }

.cell-stack { display: flex; align-items: center; gap: 5px; }
.mini-check {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 0;
  font-size: var(--fs-xs);
  font-weight: 650;
  color: var(--fg-muted);
  cursor: pointer;
  white-space: nowrap;
}
.mini-check input {
  width: auto;
  margin: 0;
  accent-color: var(--marigold);
}

/* ======================================================================
   attendance
   ====================================================================== */

.roll { display: flex; flex-direction: column; gap: 9px; }
.roll__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.roll__row[data-status='present'] { border-color: var(--grass); background: var(--grass-soft); }
.roll__row[data-status='absent'] { border-color: var(--berry); background: var(--berry-soft); }
.roll__row[data-status='late'] { border-color: var(--marigold); background: var(--marigold-soft); }
.roll__row[data-status='excused'] { border-color: var(--sky); background: var(--sky-soft); }

/* Same pill styling as the kindergarten's status picker, so it reads as one
   widget family rather than a native <select>. */
.statuspicker {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-inline-start: auto;
}
.statuspicker button {
  padding: 7px 13px;
  border: none;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--fg);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .statuspicker button:hover { background: var(--border); } }
.statuspicker button[aria-pressed='true'] { font-weight: 700; }
.statuspicker button[data-s='present'][aria-pressed='true'] { background: var(--success); color: var(--on-success); }
.statuspicker button[data-s='absent'][aria-pressed='true'] { background: var(--danger); color: var(--on-danger); }
/* White on marigold is 1.9:1. This one pill takes dark ink instead. */
.statuspicker button[data-s='late'][aria-pressed='true'] { background: var(--marigold); color: var(--on-marigold); }
.statuspicker button[data-s='excused'][aria-pressed='true'] { background: var(--info); color: var(--on-info); }

/* Month grid: one letter per day, colour plus letter so the state never
   depends on hue alone. */
.attgrid td.att {
  text-align: center;
  font-weight: 700;
  font-size: var(--fs-xs);
  padding: 6px 4px;
}
.att--present { color: var(--success); }
.att--absent { color: var(--danger); background: var(--berry-soft); }
.att--late { color: var(--warning-ink); background: var(--marigold-soft); }
.att--excused { color: var(--info); background: var(--sky-soft); }

/* ======================================================================
   dialogs
   ====================================================================== */

/* The head and foot are transparent, so a dialog is ONE uniform sheet of
   glass exactly like the sign-in card.

   Two other approaches were tried and both banded. Painting --modal-glass on
   them composites the panel colour onto itself and comes out lighter: two
   pale stripes across every dialog. A nested backdrop-filter bands too - the
   inner blur does not resolve to the same result as the panel's own.

   But a bar that is transparent cannot hide the content scrolling under it,
   and the student form and the report card both scroll. So the opaque
   version is applied only when there is actually something to hide:
   UI.modal measures the dialog on open and adds .modal--scrolls. Short
   dialogs - the confirm boxes, "forgot password" - stay a single sheet. */
.modal__head {
  padding: 22px 26px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  position: sticky;
  top: 0;
  background: transparent;
  z-index: 1;
}
.modal__head h3 { margin: 0; }
.modal__body { padding: 0 26px 8px; }
.modal__foot {
  padding: 16px 26px 24px;
  display: flex;
  justify-content: flex-end;
  gap: 11px;
  position: sticky;
  bottom: 0;
  background: transparent;
}
/* Only a dialog tall enough to scroll needs its bars to mask anything. */
.modal--scrolls .modal__head,
.modal--scrolls .modal__foot { background: var(--surface); }

[dir='rtl'] .modal__foot { justify-content: flex-start; }

/* Secondary buttons in a dialog take the glass treatment the sign-in card
   uses for "Parent portal", rather than the app's solid --surface button. On
   a glass panel a solid button reads as a different material sitting on top
   of it. The primary keeps its orange gradient - it is meant to be the one
   thing in the foot that is not glass. */
.modal__foot .btn:not(.btn--primary):not(.btn--danger) {
  background: var(--glass-strong);
  border-color: var(--glass-border);
}
@media (hover: hover) and (pointer: fine) { .modal__foot .btn:not(.btn--primary):not(.btn--danger):hover:not(:disabled) {
  background: var(--surface-alt);
} }

.formgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 15px 18px;
}
.formgrid .field--full { grid-column: 1 / -1; }
@media (max-width: 700px) { .formgrid { grid-template-columns: 1fr; } }

/* ======================================================================
   responsive
   ====================================================================== */

/* Below this width the fixed sidebar no longer fits alongside real content -
   turn it into an off-canvas drawer instead of letting the page scroll
   sideways. */
@media (max-width: 900px) {
  .menu-toggle { display: inline-flex; }
  /* The drawer slides on transform, not on its position: a transform is
     drawn by the compositor, so the slide stays smooth on an older phone.
     Closed, it sits one drawer-width beyond the inline-start edge - left in
     English, right in Pashto and Dari - and is hidden once it gets there,
     so Tab and screen readers skip it. The curve is the iOS drawer curve. */
  .nav {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: 30;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1), visibility 0s linear 0.28s;
  }
  :root[dir='rtl'] .nav { transform: translateX(100%); }
  .nav.open,
  :root[dir='rtl'] .nav.open,
  .nav.platform-nav-open {
    transform: none;
    visibility: visible;
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1), visibility 0s;
  }
  /* The backdrop fades with the slide instead of appearing at once. */
  .nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 25;
    background: rgba(23, 21, 22, 0.45);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.2s ease, visibility 0s linear 0.2s;
  }
  .nav-backdrop.open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.2s ease, visibility 0s;
  }
  @media (prefers-reduced-motion: reduce) {
    .nav, .nav.open, :root[dir='rtl'] .nav.open, .nav.platform-nav-open { transition: visibility 0s; }
    .nav-backdrop, .nav-backdrop.open { transition: visibility 0s; }
  }
  /* Stop the page scrolling behind the open drawer. */
  body.drawer-open { overflow: hidden; }

  .appbar { padding: 12px 16px; }
  .main { padding: 18px 16px; }
}

/* Everything below is about being usable with a thumb rather than a mouse. */
@media (max-width: 700px) {
  .icon-btn { width: 44px; height: 44px; }
  .btn { padding: 12px 18px; min-height: 44px; }
  .btn--sm { padding: 9px 13px; min-height: 38px; }
  .langswitch button { padding: 12px 15px; min-height: 44px; }
  .statuspicker button { padding: 10px 14px; min-height: 40px; }
  .nav a { padding: 13px; }

  /* On a phone the appbar is sticky, so every row it wraps to is a row that
     is gone from every screen for the whole session. The name goes first,
     then the role chip: "Administrator" is a wide pill telling the user
     something they already know, and it was the single item pushing Sign out
     onto a third row. Avatar and Sign out are what actually get used, and
     they now fit beside the theme and year controls.

     Measured on a 375x812 phone, with the language switcher moving to the
     sidebar at the same time: 177px over three rows, down to 123px over two.
     22% of the screen down to 15%, on a bar that is sticky. */
  .appbar__title { font-size: 18px; }
  .main { padding: 16px 14px; }
  .card__body { padding: 16px; }
  .tile__value { font-size: 27px; }
}

@media print {
  .appbar, .nav, .nav-backdrop, .toolbar, .page-head__actions { display: none !important; }
  .app { display: block; }
  .main { padding: 0; }
}

/* ------------------------------------------- light-mode login photograph

   The scrim over login-bg.jpg is hardcoded rather than tokenised, so the
   palette does not reach it on its own. Re-laid in blue here, and scoped to
   light so the dark theme keeps the teal-and-marigold original.

   The alphas are at or above the ones they replace. That matters: the
   comment on the original says every piece of text on this photo is white
   and the scrim is what holds it above 7:1, so a thinner wash would trade
   contrast for colour. Measured on the resulting ground, white lands at
   11.7:1 and the palest accent at 8.77:1.

   The three --login-accent shades follow the same pairing rule as before -
   fill, focus border, text - because one blue cannot do all three jobs on
   glass this translucent. #cfcefe measures 6.27 on this ground, which is why
   it is the fill only and never the label. */
:root:not([data-theme='dark']) .login-page {
  --login-accent: #cfcefe;
  --login-accent-soft: #e2e1ff;  /* the focus border: 7.76:1, and a graphic needs 3 */
  --login-accent-text: #e2e1ff;  /* the floating label and the link: 10.10:1 */
  background-color: #232a3a;
  background-image:
    linear-gradient(160deg, rgba(35, 42, 58, 0.78) 0%, rgba(52, 62, 86, 0.68) 55%, rgba(52, 62, 86, 0.74) 100%),
    radial-gradient(circle at 15% 20%, rgba(226, 225, 255, 0.22) 0, transparent 42%),
    radial-gradient(circle at 85% 80%, rgba(207, 206, 254, 0.4) 0, transparent 46%),
    url('/img/login-bg.jpg');
}

@media (max-width: 900px) {
  :root:not([data-theme='dark']) .login-page {
    background-image:
      linear-gradient(160deg, rgba(35, 42, 58, 0.78) 0%, rgba(52, 62, 86, 0.68) 55%, rgba(52, 62, 86, 0.74) 100%),
      radial-gradient(circle at 15% 20%, rgba(226, 225, 255, 0.22) 0, transparent 42%),
      radial-gradient(circle at 85% 80%, rgba(207, 206, 254, 0.4) 0, transparent 46%),
      url('/img/login-bg-sm.jpg');
  }
}


/* --------------------------------------------- sidebar icons, left as they were

   The sidebar GROUND follows the blue palette like the rest of light mode.
   Its icon circles do not: they keep one crayon per section, which is how
   somebody finds Attendance without reading the label.

   Only the four whose tokens the palette re-pointed are restated below.
   dashboard, classes, attendance and fees are absent on purpose: grass,
   marigold, sky and berry keep their hue in both themes already, so those
   circles never changed and naming them here would be a second place to keep
   in step for no benefit. */

/* Keeps the hairline the shared rule gives it. The ground is blue here rather
   than teal, which lifts this circle from 2.33:1 against it to 2.54 - better,
   and still short of the 3:1 a graphic owes, so the hairline is still what
   makes the edge findable. */

/* ------------------------------------------- dashboard tile pegs, as they were

   Same reasoning as the sidebar icons above, and the same shortlist: only the
   pegs whose tokens the palette re-pointed are restated. 2, 3, 4 and 7 are
   absent because marigold, grass, sky and berry keep their hue in both themes.

   These matter more than they look. A tile and its sidebar entry are meant to
   carry the same section colour so the two match at a glance - restoring one
   set and not the other would have left that pairing half-true. */

:root:not([data-theme='dark']) .tile--danger { border-color: #ffd0d6; }

/* The panel still opens and closes, it just arrives rather than slides. */
@media (prefers-reduced-motion: reduce) {
  .nav,
  .app,
    .nav__brandtext,
  .nav__label,
  .nav__foot {
    transition: none;
  }
}


/* Dark mode keeps #232a3a.

   It was pinned there so the two themes had one sidebar. Light is a frosted
   panel now, so they cannot match any more - but dark's --teal-deep is a
   deep teal, and simply dropping the pin would have slid dark's sidebar back
   to it, which is a change to a theme nobody asked to change. The value
   stays; only the reason for it is different. */
:root[data-theme='dark'] .nav {
  background: #232a3a;
}
:root[data-theme='dark'] .langswitch--nav button[aria-pressed='true'] {
  color: #232a3a;
}

/* ============================================================ LIGHT SIDEBAR

   In light mode the sidebar is a frosted light panel rather than the dark
   ground it keeps in dark mode.

   The blur is not decoration here. The panel is fixed and the page passes
   UNDER it - on hover it sits over the roll - so backdrop-filter has real
   content to work on: the table softens behind the glass exactly where the
   reference blurs its wallpaper. On a page that did not scroll beneath it
   this would be an expensive way to draw a flat colour.

   saturate() for the same reason it is on the login card: without it the
   glass drains the colour out of everything behind it.

   The crayon tiles are untouched. They are saturated enough to hold their
   own on a light ground, and they are the thing somebody navigates by. */

/* Solid white, not frosted. The blur was earning its keep while the page
   scrolled underneath a floating panel; against a flush column there is
   nothing behind it to soften, and it would be an expensive way to draw a
   flat colour. */
:root:not([data-theme='dark']) .nav {
  background: var(--surface);
  background-image: none;
  border-inline-end: 1px solid var(--border);
  color: var(--fg);
}

:root:not([data-theme='dark']) .nav a { color: var(--fg); }
@media (hover: hover) and (pointer: fine) { :root:not([data-theme='dark']) .nav a:hover {
  background: var(--surface-alt);
  color: var(--fg);
} }
:root:not([data-theme='dark']) .nav__label,
:root:not([data-theme='dark']) .nav__role { color: var(--fg-subtle); }
:root:not([data-theme='dark']) .nav__name { color: var(--fg); }
:root:not([data-theme='dark']) .nav__divider { background: rgba(32, 34, 42, 0.12); }

:root:not([data-theme='dark']) .nav__avatar {
  background: var(--primary);
  color: #fff;
}

/* A fourth casualty of the same sweep: this read
   `:root:not(...) :root:not(...) .nav__foot`, a :root nested inside a :root,
   which matches nothing at all - so the foot had no light styling. */
:root:not([data-theme='dark']) .nav__foot {
  background: rgba(255, 255, 255, 0.66);
  border-color: rgba(23, 21, 22, 0.1);
}
:root:not([data-theme='dark']) .langswitch--nav { border-color: rgba(23, 21, 22, 0.16); }
:root:not([data-theme='dark']) .langswitch--nav button {
  background: rgba(255, 255, 255, 0.7);
  color: var(--fg-muted);
}
@media (hover: hover) and (pointer: fine) { :root:not([data-theme='dark']) .langswitch--nav button:hover { background: #fff; } }
/* The same pastel-and-dark-ink pill as the page marker directly above it -
   these two sit in one panel, and --primary would have made one of them the
   deep ink and the other the pastel. */
:root:not([data-theme='dark']) .langswitch--nav button[aria-pressed='true'] {
  background: var(--accent);
  color: #20222a;
}

/* ------------------------------------------------- outline icons, no tiles

   The tiles are gone. Every section icon is a line drawing in the row's own
   colour, and the page you are on is marked by a bar on the panel's leading
   edge instead of by a filled square.

   The box around the glyph stays 30px even though the glyph is 21px. That is
   not spare padding - it is what keeps an icon's centre on the 39px line
   that the collapsed rail is built around, so removing the tile changed how
   the icons LOOK without moving any of them. */
.nav__icon {
  background: none;
  border-radius: 0;
  color: inherit;
  box-shadow: none;
}
.nav__icon svg {
  width: 20px;
  height: 20px;
}

/* The marker for the current page: a bar at the PANEL's edge, not a fill on
   the row. -12px reaches back through .nav's own padding to the edge itself,
   and every corner radius here is logical, so the bar sits on the right in
   Pashto and Dari and on the left in English without a second rule. */
.nav a { position: relative; }
.nav a[aria-current='page']::before {
  content: '';
  position: absolute;
  inset-inline-start: -12px;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 23px;
  background: var(--marker);
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  border-start-end-radius: 3px;
  border-end-end-radius: 3px;
}

/* The dashboard tiles follow: one colour, and the two that report a RESULT
   keep theirs, because pass and fail are the numbers somebody is looking
   for. */

/* =================================================== THE SIDEBAR, RESTATED

   A flat, airy panel: outline icons, no filled rows, and the current page
   marked by a bar on the leading edge.

   --marker is the one thing both themes set differently and everything else
   reads from, so the two variants below are a handful of colours rather than
   two copies of the design. */

.nav a {
  /* Lighter than a navigation item usually is. With the tiles gone there is
     nothing else competing, so the label can stop shouting. */
  font-weight: 500;
  gap: 14px;
}
@media (hover: hover) and (pointer: fine) { .nav a:hover { background: var(--nav-hover); } }
.nav a[aria-current='page'] {
  background: var(--nav-active);
  font-weight: 700;
}

/* The brand block: a rounded card holding the initials, the way the
   reference frames its logo, rather than a bare circle. */
.nav__avatar {
  border-radius: 13px;
  font-weight: 700;
}


/* --- light ------------------------------------------------------------- */

/* The tinted sheet this block used to paint was written for the previous
   reference, where the sidebar floated on the ground. This one is a white
   column, so the tint is gone and only the row colours are left here. */
:root:not([data-theme='dark']) .nav {
  --marker: #00719c;
  --nav-hover: var(--surface-alt);
  --nav-active: var(--sky);
}
:root:not([data-theme='dark']) .nav a { color: var(--fg-muted); }
@media (hover: hover) and (pointer: fine) { :root:not([data-theme='dark']) .nav a:hover { color: var(--fg); } }
:root:not([data-theme='dark']) .nav__avatar {
  background: var(--sky);
  color: #20222a;
}

/* --- dark -------------------------------------------------------------- */

/* The same design on a dark ground: the panel goes deep navy, the icons and
   labels lift to a light slate, and the marker becomes the light blue - the
   dark blue that marks the light panel would vanish against this one. */
:root[data-theme='dark'] .nav {
  --marker: #cfcefe;
  --nav-hover: rgba(255, 255, 255, 0.06);
  --nav-active: rgba(207, 206, 254, 0.16);
  background: #232a3a;
  background-image: none;
  border-inline-end: 1px solid rgba(255, 255, 255, 0.07);
}
:root[data-theme='dark'] .nav a { color: #b3b8c4; }
@media (hover: hover) and (pointer: fine) { :root[data-theme='dark'] .nav a:hover { color: #eef0f4; } }
:root[data-theme='dark'] .nav a[aria-current='page'] { color: #cfcefe; }
:root[data-theme='dark'] .nav__avatar {
  background: rgba(255, 255, 255, 0.1);
  color: #e8eaf0;
  box-shadow: none;
}
:root[data-theme='dark'] .nav__name { color: #e8eaf0; }
:root[data-theme='dark'] .nav__role,
:root[data-theme='dark'] .nav__label { color: #a2a8b6; }
:root[data-theme='dark'] .nav__divider { background: rgba(255, 255, 255, 0.09); }
:root[data-theme='dark'] .nav__foot {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.08);
}

/* The current page is a filled pill, the way the reference marks it, rather
   than a bar at the panel's edge - a panel that is inset on every side has no
   edge to put a bar against. */
.nav a[aria-current='page']::before { display: none; }
.nav a {
  border-radius: 12px;
}
/* Theme-scoped, because the frosted-sidebar block earlier in this file
   carries a :root prefix and would otherwise keep winning with its own
   tint. The pill is --accent, the brand pastel, in BOTH themes rather than
   --primary, which resolves to the deep ink in light and would have made the
   one saturated block on an otherwise pastel screen. Dark ink on it measures
   5.96:1, the same pairing the primary button uses. */
/* The reference marks the page you are on with a PALE BLUE pill and the same
   near-black it uses everywhere else - 12.47:1 - with the icon lifted onto a
   white square inside it.

   The icon used to be set to white here, which was right when this pill was
   a saturated fill and wrong the moment it became a pastel: white on #C4EAFB
   is 1.27:1, so the icon on the current page was the one icon in the sidebar
   nobody could see. */
:root:not([data-theme='dark']) .nav a[aria-current='page'],
:root[data-theme='dark'] .nav a[aria-current='page'] {
  background: var(--sky);
  color: #20222a;
  font-weight: 650;
}
:root:not([data-theme='dark']) .nav a[aria-current='page'] .nav__icon,
:root[data-theme='dark'] .nav a[aria-current='page'] .nav__icon {
  color: #20222a;
}

/* --- the reference sidebar, measured -----------------------------------

   Sampled off the supplied crop rather than read by eye:

     pill        #c2e6f8 in the crop, #c4eafb in the full-size reference -
                 the same colour through two exports, so the --sky token
                 it matches; 12px corners, 50px row pitch
     active ink  #2c2e2e   (10.4:1 on the pill - kept as the near-black)
     glyphs      #252627   near-black on EVERY row, not only the active one
     idle label  #848688   3.65:1 on white
     heading     #a1a3a5   2.53:1 on white

   The last two are the only values not taken as measured. Both are under
   the 4.5 a word owes, and this palette already deepens exactly these two
   greys (to 6.09 and 4.52) because a school office reads this column all
   day. Everything else is the crop's.

   The pill is 44px rather than the crop's 39 - 39 is under the touch floor
   - so the rows are spaced 6px apart to land on the same 50px pitch. */
.nav__group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nav__group + .nav__group { margin-block-start: 30px; }

/* The glyph is dark while the label beside it is grey: in the crop the
   icons read as the stronger mark, and they stay that way on idle rows. */
:root:not([data-theme='dark']) .nav__icon { color: var(--fg); }

/* MENU and OTHER: small, spaced capitals, at the weight the crop sets them
   rather than bold. */
.nav__label {
  font-weight: 500;
  letter-spacing: 0.08em;
  margin-block-end: 8px;
}


/* ================================================ THE SIDEBAR, NO LONGER MOVING

   The panel is simply there: full width, inset on all four sides, present on
   every screen. It used to be a 78px rail that opened on hover, with a pin to
   keep it open; all of that is gone, along with the label fading and the
   focus-within handling the collapse needed.

   Nothing is lost by removing it except the animation. A sidebar that is
   always open is one the office never has to discover, and the gutter is the
   same width the pinned state reserved anyway. */
@media (min-width: 901px) {
  .app {
    padding-inline-start: var(--rail-open);
  }
  /* Flush to the edge and full height, the way the reference draws it: a
     white column the page sits beside, rather than a panel floating on the
     ground. The inset version came from a different reference; keeping both
     would have been half of each. */
  .nav {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--rail-open);
    height: 100vh;
    height: 100dvh;
    overscroll-behavior: contain;
    padding-inline: 14px;
    border-radius: 0;
    box-shadow: none;
    overflow-x: hidden;
    overflow-y: auto;
  }
}

/* ======================================================================
   the reference's shell: a white column, a product mark, a user chip
   ====================================================================== */

/* --- the sidebar's brand ------------------------------------------------ */

.nav__logo {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 11px;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--surface-alt);
}
.nav__logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.nav__brand .nav__name {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 650;
  line-height: 1.2;
}

/* --- the user chip in the appbar ---------------------------------------- */

.user-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.user-chip__text {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
  min-width: 0;
}
[dir='ltr'] .user-chip__text { align-items: flex-start; }
.user-chip__name {
  font-weight: 700;
  font-size: var(--fs-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 11rem;
}
.user-chip__role {
  font-size: var(--fs-xs);
  color: var(--fg-subtle);
}
.user-chip__avatar {
  width: 38px;
  height: 38px;
  flex: none;
  background: var(--sky);
  color: #20222a;
  font-weight: 700;
}
/* On a phone the appbar already carries the menu button, the year and sign
   out. The name is the first thing to go; the avatar stays, because it is
   what tells somebody which account they are in. */
@media (max-width: 760px) {
  .user-chip__text { display: none; }
}

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

   Flat pastel fills with no shadow, alternating lavender and yellow across
   the row, exactly as the reference lays them out.

   The alternation is decoration, so it only applies to tiles that have no
   meaning of their own. A tile that reports "present today" or "unpaid"
   keeps its own colour: losing that would turn the one row on this screen
   that says something into a row that just looks nice. */
.tile {
  box-shadow: none;
  border-radius: 18px;
  padding: 20px 18px;
}
.tile:not([class*='tile--']):nth-child(odd) { background: var(--violet); }
.tile:not([class*='tile--']):nth-child(even) { background: var(--marigold); }
.tile__label {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-sm);
  order: 2;
  margin-block: 4px 0;
}
.tile__value { order: 1; }
.tile__meta { order: 3; }
.tile {
  display: flex;
  flex-direction: column;
}
/* On a pastel fill the label's muted grey drops toward the ground it sits
   on. The near-black the numbers use carries it instead, at 70% weight. */
.tile:not([class*='tile--']) .tile__label,
.tile:not([class*='tile--']) .tile__meta { color: #3d4049; }
.tile:not([class*='tile--']) .tile__value { color: #20222a; }

/* ======================================================================
   the dashboard the reference lays out

   Two columns: the year on the left, today on the right. Everything in
   both is drawn from data the app already holds - see the note above the
   chart helpers in views/dashboard.js for why there is no message panel.
   ====================================================================== */

.dash-grid {
  margin-block-start: var(--gap);
  display: grid;
  grid-template-columns: minmax(0, 1fr) 21rem;
  gap: var(--gap);
  align-items: start;
}
.dash-main,
.dash-rail {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  min-width: 0;
}
/* Two charts side by side, and never narrower than they can be read at. */
.dash-pair {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: var(--gap);
}
.dash-card { margin: 0; }

/* --- charts -------------------------------------------------------------- */

.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart--bars { max-height: 15rem; }
.chart--area { max-height: 13rem; }
.chart__peak {
  font-size: var(--fs-sm);
  color: var(--fg-subtle);
  margin-block-end: 8px;
}

.donutwrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.donut { position: relative; width: 11rem; max-width: 100%; }
.donut__mid {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  pointer-events: none;
}
.donut__total {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 650;
  line-height: 1;
}
.donut__cap {
  font-size: var(--fs-xs);
  color: var(--fg-subtle);
  margin-block-start: 2px;
}

.legend {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  justify-content: center;
}
.legend--row { justify-content: flex-start; margin-block-end: 10px; }
.legend__item { display: flex; align-items: center; gap: 9px; }
.legend__pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-sm);
  color: var(--fg-muted);
}
.legend__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex: none;
}
.legend__value { font-weight: 700; line-height: 1.2; }
.legend__label { font-size: var(--fs-xs); color: var(--fg-subtle); }

/* --- the week strip ------------------------------------------------------ */

.weekstrip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 3px;
  text-align: center;
}
.weekday {
  padding: 8px 2px;
  border-radius: 12px;
  min-width: 0;
}
.weekday__name {
  font-size: 11px;
  color: var(--fg-subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.weekday__num {
  font-weight: 700;
  font-size: var(--fs-base);
  margin-block-start: 2px;
}
.weekday--now {
  background: var(--sky);
  color: #20222a;
}
.weekday--now .weekday__name { color: #3d4049; }

/* --- the agenda ---------------------------------------------------------- */

.agenda { display: flex; flex-direction: column; gap: 9px; }
.agenda__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border-radius: 14px;
  /* The bar on the leading edge is the reference's, and it is logical so it
     sits on the right in Pashto and the left in English. */
  border-inline-start: 3px solid var(--accent);
  background: var(--coral-soft);
}
.agenda__row--1 { border-inline-start-color: var(--marigold); background: var(--marigold-soft); }
.agenda__row--2 { border-inline-start-color: var(--sky); background: var(--sky-soft); }
.agenda__time {
  font-size: var(--fs-sm);
  font-weight: 650;
  color: var(--fg-muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.agenda__meta { font-size: var(--fs-xs); color: var(--fg-subtle); }
.agenda__what { font-weight: 650; line-height: 1.3; }

@media (max-width: 1100px) {
  .dash-grid { grid-template-columns: minmax(0, 1fr); }
  .dash-pair { grid-template-columns: minmax(0, 1fr); }
}

/* --- the dashboard's wide pair and its stat card ------------------------

   The reference sets a wide chart beside a narrow card at the bottom of the
   main column. The narrow one is a single number with an icon above it,
   which is a different shape from the tiles at the top - those are a row of
   equals, this is a caption on the chart beside it. */
.dash-pair--wide { grid-template-columns: minmax(0, 1fr) minmax(0, 15rem); }

.dash-stat { display: flex; }
.dash-stat .card__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  width: 100%;
}
.dash-stat__icon {
  width: 44px;
  height: 44px;
  border-radius: 13px;
  display: grid;
  place-items: center;
  background: var(--sky-soft);
  color: var(--sky-ink);
  margin-block-end: 12px;
}
.dash-stat__icon svg { width: 22px; height: 22px; }
.dash-stat__value {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 650;
  line-height: 1.15;
}
.dash-stat__label { font-weight: 650; }
.dash-stat__meta { font-size: var(--fs-sm); color: var(--fg-subtle); }

/* --- the calendar head --------------------------------------------------- */

.calhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.calhead .card__title { flex: 1; text-align: center; }
.icon-btn--sm { width: 30px; height: 30px; }
/* One chevron path serves both arrows; the forward one is mirrored. A class
   rather than a style attribute, because the CSP sets style-src 'self'. */
.icon--flip { transform: scaleX(-1); }

/* The week cells are buttons now - picking one loads that day's agenda. */
button.weekday {
  border: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: transparent;
}
@media (hover: hover) and (pointer: fine) { button.weekday:hover { background: var(--surface-alt); } }
@media (hover: hover) and (pointer: fine) { button.weekday--now:hover { background: var(--sky); } }

@media (max-width: 1100px) {
  .dash-pair--wide { grid-template-columns: minmax(0, 1fr); }
}

/* --- the reference's coloured stat cards ---------------------------------

   The Make source paints its four stat cards in alternating lavender and
   amber fills, each with a change pill and a decorative circle bleeding off
   the bottom corner, rather than the white cards the rest of the grid uses.

   The value stays near-black rather than taking the crayon ink. That is both
   what the design does (#2D2D5E on the fill) and what this palette already
   requires: the fills measure 1.5:1 and 1.3:1 on white and are only ever
   painted behind something, with the near-black on top. The crayon ink
   carries the label and the pill, where it clears 4.5:1 on its own tint. */
.tile--fill {
  background: var(--tile-fill);
  box-shadow: none;
  overflow: hidden;
  padding: 16px 18px 18px;
}
.tile--fill .tile__label {
  color: var(--tile-ink);
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  margin-block-end: 0;
  margin-block-start: 4px;
  order: 3;
}
.tile--fill .tile__value { color: var(--fg); order: 2; }
.tile--fill .tile__meta { color: var(--tile-ink); opacity: .85; order: 4; }
.tile--fill { display: flex; flex-direction: column; }

/* Bottom-inline-end in logical terms, so it bleeds off the correct corner
   in Pashto and Dari without a [dir] block. */
.tile--fill::after {
  content: '';
  position: absolute;
  inset-block-end: -16px;
  inset-inline-end: -16px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: rgb(255 255 255 / .28);
  pointer-events: none;
}

.tile--lavender { --tile-fill: var(--coral); --tile-ink: var(--coral-ink); }
.tile--amber    { --tile-fill: var(--marigold); --tile-ink: var(--marigold-ink); }

/* The pill is only drawn when there is a real figure to put in it. */
.tile__trend {
  order: 1;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgb(255 255 255 / .72);
  color: var(--tile-ink);
  font-size: 12px;
  font-weight: 650;
  border-radius: 999px;
  padding: 2px 9px;
  margin-block-end: 10px;
}
.tile__trend svg { width: 10px; height: 10px; }

/* --- the template's lower rows ------------------------------------------

   The preview file puts TWO small accent cards stacked beside the wide
   earnings chart, then a three-card row under the whole thing. The Make
   rebuild of this template dropped both; the flat preview has them. */
.dash-stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  min-width: 0;
}
.dash-stack .dash-stat { flex: 1; }

.dash-trio {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap);
}

/* A list card's body scrolls rather than stretching the row: the three
   cards in the reference are the same height whatever is in them. */
.dash-list { max-height: 15rem; overflow-y: auto; }
.dash-list__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-block-end: 1px solid var(--border);
}
.dash-list__row:last-child { border-block-end: none; }
.dash-list__main { flex: 1; min-width: 0; }
.dash-list__title {
  font-weight: 650;
  font-size: 13.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dash-list__meta { font-size: 12px; color: var(--fg-subtle); }
.dash-list__num { font-size: 13px; font-weight: 650; white-space: nowrap; }

@media (max-width: 1100px) {
  .dash-trio { grid-template-columns: minmax(0, 1fr); }
}

/* ======================================================= THE FINANCE MENU

   A parent row that opens its pages beneath it. When one of them is the
   page you are on, the PARENT wears the pill and the page itself is marked
   only by darker text and a line on the leading edge - one pill per sidebar,
   as in the reference. */
.nav__parent {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 7px 13px;
  border: none;
  border-radius: 12px;
  background: none;
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 500;
  text-align: start;
  cursor: pointer;
}
:root:not([data-theme='dark']) .nav__parent { color: var(--fg-muted); }
:root[data-theme='dark'] .nav__parent { color: #b3b8c4; }
@media (hover: hover) and (pointer: fine) { .nav__parent:hover { background: var(--nav-hover); } }
@media (hover: hover) and (pointer: fine) { :root:not([data-theme='dark']) .nav__parent:hover { color: var(--fg); } }
@media (hover: hover) and (pointer: fine) { :root[data-theme='dark'] .nav__parent:hover { color: #eef0f4; } }
.nav__parent--current,
:root:not([data-theme='dark']) .nav__parent--current,
:root[data-theme='dark'] .nav__parent--current {
  background: var(--sky);
  color: #20222a;
  font-weight: 650;
}
.nav__parent .nav__text { flex: 1; }

/* A chevron pointing down when open, and toward the reading direction when
   shut - right in English, left in Pashto and Dari. */
.nav__chev { display: flex; width: 18px; transition: transform 0.15s cubic-bezier(0.23, 1, 0.32, 1); }
.nav__chev svg { width: 18px; height: 18px; }
.nav__parent[aria-expanded='false'] .nav__chev { transform: rotate(-90deg); }
[dir='rtl'] .nav__parent[aria-expanded='false'] .nav__chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .nav__chev { transition: none; } }

/* The two pages, indented under the parent's label with the reference's
   pale-blue rule down their leading edge. [hidden] has to be restated: a
   display value on the class would otherwise beat the browser's own. */
.nav__sub {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-block: 4px 2px;
  margin-inline-start: 28px;
  padding-inline-start: 14px;
  border-inline-start: 2px solid var(--sky);
}
.nav__sub[hidden] { display: none; }
.nav .nav__sub a { padding: 8px 12px; font-weight: 500; }
:root:not([data-theme='dark']) .nav .nav__sub a[aria-current='page'],
:root[data-theme='dark'] .nav .nav__sub a[aria-current='page'] {
  background: none;
  font-weight: 650;
}
:root:not([data-theme='dark']) .nav .nav__sub a[aria-current='page'] { color: var(--fg); }
:root[data-theme='dark'] .nav .nav__sub a[aria-current='page'] { color: #eef0f4; }

/* =============================================== THE FINANCE SCREENS

   Fees collection and school expenses share one layout, taken from the
   reference: a year chart beside four stat cards, then the ledger in a card
   of its own. Colours are sampled from the reference; where its text inks
   measured under 4.5:1, the same hue is deepened until it passes. */

.fin-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 25rem);
  gap: var(--gap);
  margin-block-end: var(--gap);
}
.fin-chart { margin: 0; }
.fin-chart .card__body { padding-block-start: 4px; }

.fin-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}
.fin-card {
  display: flex;
  flex-direction: column;
  min-height: 132px;
  padding: 16px 16px 18px;
  border-radius: var(--r);
  background: var(--sky);
  color: #191c22;
  /* The number is sized to the card, not the window: an afghani amount
     carries a three-letter unit the reference's dollar sign does not, and
     on a laptop the card is narrow enough for that to push it onto two
     lines. It shrinks only as far as it has to, and caps at the design size. */
  container-type: inline-size;
}
/* Money going out wears the lavender instead, so the two screens do not
   read as the same page. */
.fin-card--out { background: var(--coral); }
.fin-card__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-block-end: auto;
}
.fin-card__value {
  margin-block-start: 14px;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 13cqi, 1.75rem);
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.fin-card__label { margin-block-start: 4px; font-size: 14px; color: #30464c; }
.fin-card--out .fin-card__label { color: var(--fg); }

/* The wave: white on the fill, as the reference draws it. Decoration beside
   the number, hidden from screen readers. */
.spark { width: 64px; height: 26px; }
.spark__line { fill: none; stroke: #ffffff; stroke-width: 2.2; stroke-linecap: round; }

/* The change pill. The reference's green and red measure 3.52 and 3.66:1 on
   the white pill; these are the same hues at 5.27 and 5.44. */
.fin-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 9px;
  border-radius: 999px;
  background: #ffffff;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.fin-pill svg { width: 10px; height: 10px; display: block; }
.fin-pill--up { color: #0b7a64; }
.fin-pill--down { color: #c62f37; }

/* --- the ledger card ---------------------------------------------------- */

.fin-table { margin: 0; padding: 20px 22px 18px; }
.fin-table__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px 16px;
  margin-block-end: 16px;
}
.fin-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }

.fin-glyph { display: inline-flex; }
.fin-glyph svg { width: 18px; height: 18px; display: block; }

/* Search: a pill with the magnifier inside it. */
.fin-search {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 15rem;
  height: 40px;
  padding-inline: 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--fg-subtle);
}
.fin-search:focus-within { border-color: var(--coral-ink); box-shadow: 0 0 0 3px var(--coral-soft); }
.fin-search input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  outline: none;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  color: var(--fg);
  box-shadow: none;
}

/* The filters: flat grey pills, as the reference sets them, with the chevron
   drawn by the stylesheet so it sits on the correct side in both directions. */
.fin-select {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding-inline-start: 12px;
  border-radius: 12px;
  background: var(--bg);
  color: var(--fg);
}
.fin-select select {
  height: 100%;
  border: none;
  background-color: transparent;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2320222a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 14px;
  background-position: right 10px center;
  appearance: none;
  -webkit-appearance: none;
  padding-block: 0;
  padding-inline: 2px 32px;
  font: inherit;
  font-size: 14px;
  color: inherit;
  box-shadow: none;
  cursor: pointer;
}
[dir='rtl'] .fin-select select { background-position: left 10px center; }
.fin-select:focus-within { box-shadow: 0 0 0 3px var(--coral-soft); }

/* The table lives inside the card, so it drops the floating treatment every
   other list has - a shadow inside a shadow reads as a card in a card. */
.fin-tablewrap { box-shadow: none; border-radius: 0; background: transparent; }
.fin-grid thead th { padding: 16px 10px; font-size: 14px; }
.fin-grid thead th:first-child { border-start-start-radius: 14px; border-end-start-radius: 14px; }
.fin-grid thead th:last-child { border-start-end-radius: 14px; border-end-end-radius: 14px; }
.fin-grid thead th { border-block-end: none; }
.fin-grid tbody td {
  padding: 14px 10px;
  border-block-end: 1px solid var(--coral-soft);
  font-size: 14px;
  white-space: nowrap;
}

.fin-person { display: flex; align-items: center; gap: 12px; }
.fin-avatar { width: 40px; height: 40px; font-size: 14px; }
.fin-person__text { min-width: 0; }
.fin-person__name { font-weight: 500; white-space: nowrap; }
.fin-person__meta { font-size: 13px; color: var(--fg-subtle); white-space: nowrap; }

/* Status chips. The text is the reference's hue deepened to pass on its own
   tint; the dot keeps the reference's bright colour, since it only repeats
   what the word already says. */
.fin-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.fin-chip__dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.fin-chip--paid { background: var(--sky-soft); color: #0375a8; }
.fin-chip--paid .fin-chip__dot { background: #49bfeb; }
.fin-chip--pending { background: #fff6e8; color: #a8500a; }
.fin-chip--pending .fin-chip__dot { background: #f7ae59; }
.fin-chip--overdue { background: var(--berry-soft); color: #c8102e; }
.fin-chip--overdue .fin-chip__dot { background: #fa525e; }
.fin-chip--unbilled { background: var(--surface-alt); color: var(--fg-muted); }
.fin-chip--unbilled .fin-chip__dot { background: var(--border-strong); }
.fin-chip--cat { background: var(--coral-soft); color: var(--coral-ink); }
.fin-chip--cat .fin-chip__dot { background: var(--coral-ink); }
:root[data-theme='dark'] .fin-chip--paid { color: #9fdcf5; }
:root[data-theme='dark'] .fin-chip--pending { background: rgba(247, 174, 89, 0.16); color: #f7c485; }
:root[data-theme='dark'] .fin-chip--overdue { color: #ff9aa2; }

.fin-actions { display: inline-flex; gap: 4px; }
.fin-actions .icon-btn { color: var(--fg-subtle); }

/* A voided expense stays listed, struck through, beside the chip that says so. */
.fin-row--voided td { color: var(--fg-subtle); }
.fin-row--voided .fin-strike { text-decoration: line-through; }

.fin-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block-start: 16px;
}
.fin-pager__info { color: var(--fg-muted); font-size: 14px; }

/* --- the year chart ----------------------------------------------------- */

.chart--year { width: 100%; height: auto; display: block; overflow: visible; }
.chart-grid { stroke: var(--border); stroke-dasharray: 4 5; }
.chart-axis { fill: var(--fg-subtle); font-size: 12px; }
.chart-line { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.chart--yellow .chart-line,
.chart--yellow .chart-marker { stroke: var(--marigold); }
.chart--yellow .chart-dot { fill: var(--marigold); }
.chart--yellow .chart-fill-top { stop-color: var(--marigold); stop-opacity: 0.5; }
.chart--yellow .chart-fill-bottom { stop-color: var(--marigold); stop-opacity: 0; }
.chart--lavender .chart-line,
.chart--lavender .chart-marker { stroke: var(--coral-ink); }
.chart--lavender .chart-dot { fill: var(--coral-ink); }
.chart--lavender .chart-fill-top { stop-color: var(--coral); stop-opacity: 0.75; }
.chart--lavender .chart-fill-bottom { stop-color: var(--coral); stop-opacity: 0; }
.chart-marker { stroke-width: 3; stroke-linecap: round; }
.chart-dot { stroke: #ffffff; stroke-width: 3; }
.chart-tip__box { fill: var(--surface); filter: drop-shadow(0 4px 12px rgba(32, 34, 42, 0.14)); }
.chart-tip__value { fill: var(--fg); font-size: 15px; font-weight: 700; }
.chart-tip__date { fill: var(--fg-subtle); font-size: 11.5px; }
.chart-hit { fill: transparent; cursor: default; outline: none; }
.chart-hit:focus-visible { fill: var(--coral-soft); fill-opacity: 0.6; }

@media (max-width: 1180px) {
  .fin-top { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .fin-cards { grid-template-columns: minmax(0, 1fr); }
  .fin-search { min-width: 0; flex: 1; }
}

/* Supplied Finance design, scoped to fees so other office screens retain
   their own layout. Logical properties also support Pashto and Dari. */
.finance-page { --gap: 18px; }
.finance-page .fin-top { grid-template-columns: minmax(0, 1fr) 386px; }
.finance-page .card { border-radius: 15px; box-shadow: 0 2px 10px rgba(45,60,80,.025); }
.finance-page .fin-chart { min-width: 0; min-height: 306px; }
.finance-page .fin-chart .card__head { padding: 18px 18px 8px; border: 0; }
.finance-page .card__title { font-size: 18px; font-weight: 700; }
.finance-page .fin-chart .card__body { padding: 0 18px 12px; }
.finance-page .chart--year { height: 245px; }
.finance-page .fin-card { min-height: 143px; border-radius: 14px; padding: 20px 18px 15px; background: #bdeeff; }
.finance-page .fin-card__value { font-family: inherit; font-size: clamp(18px, 12cqi, 24px); font-weight: 700; margin-block-start: 16px; }
.finance-page .fin-card__label { font-size: 12px; margin-block-start: 7px; }
.finance-page .spark { width: 50px; height: 26px; }
.finance-page .fin-pill { font-size: 10px; padding: 4px 7px; }
.finance-page .fin-table { border-radius: 17px; padding: 18px 18px 8px; }
.finance-page .fin-search { width: 255px; min-width: 0; height: 36px; padding-inline: 11px; }
.finance-page .fin-search input { font-size: 12px; }
.finance-page .fin-select { height: 36px; border-radius: 7px; }
.finance-page .fin-select select { font-size: 12px; }
.finance-page .fin-grid { min-width: 990px; }
.finance-page .fin-grid thead th { height: 54px; padding: 0 15px; font-size: 12.5px; font-weight: 500; }
.finance-page .fin-grid thead th:first-child { border-radius: 0; border-start-start-radius: 9px; }
.finance-page .fin-grid thead th:last-child { border-radius: 0; border-start-end-radius: 9px; }
.finance-page .fin-grid tbody td { height: 70px; padding: 0 15px; font-size: 12.5px; border-color: var(--border); }
.finance-page .fin-grid th:last-child, .finance-page .fin-grid td:last-child { text-align: center; }
.finance-page .fin-grid .fin-check-cell { width: 40px; padding-inline: 12px; }
.fin-check { appearance: none; width: 15px; height: 15px; padding: 0; margin: 0; border: 1.4px solid #949da6; border-radius: 4px; background: var(--surface); display: inline-grid; place-content: center; cursor: pointer; vertical-align: middle; }
.fin-check:checked, .fin-check:indeterminate { background: #4ac8ee; border-color: #4ac8ee; }
.fin-check:checked::after { content: '✓'; font-size: 11px; line-height: 1; color: white; }
.fin-check:indeterminate::after { content: '−'; font-size: 12px; line-height: 1; color: white; }
.fin-check:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }
.finance-page .fin-person { gap: 10px; }
.finance-page .fin-avatar { width: 38px; height: 38px; font-size: 12px; }
.finance-page .fin-person__meta { font-size: 11px; margin-block-start: 3px; }
.finance-page .fin-chip { padding: 6px 10px; font-size: 11.5px; font-weight: 500; }
:root:not([data-theme='dark']) .finance-page .card { background: #fff; }
:root:not([data-theme='dark']) .finance-page .fin-grid thead th { background: #e8f8ff; color: #42474b; }
:root:not([data-theme='dark']) .finance-page .fin-grid tbody tr.selected { background: #f1efff; }
:root:not([data-theme='dark']) .finance-page .fin-select { background: #f6f7f9; }
:root:not([data-theme='dark']) .finance-page .chart--yellow { --marigold: #ffd85b; }
:root[data-theme='dark'] .finance-page .fin-grid tbody tr.selected { background: #37314c; }
@media (max-width: 1180px) {
  .finance-page .fin-top { grid-template-columns: minmax(0, 1fr); }
  .finance-page .fin-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .finance-page .fin-card { min-height: 120px; }
}
@media (max-width: 820px) {
  .finance-page .fin-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .finance-page .fin-table__head { align-items: flex-start; flex-direction: column; }
  .finance-page .fin-toolbar { width: 100%; }
  .finance-page .fin-search { width: 100%; flex: 1 1 100%; }
  .finance-page .fin-table { padding-inline: 12px; }
}

/* Mehrawaran sidebar supplied design. Keep the existing role-based links
   and mobile drawer, with the compact white panel and cyan current item. */
:root { --rail-open: 205px; }
.nav { width: 205px; padding: 28px 16px 24px; gap: 0; }
:root:not([data-theme='dark']) .nav { background: #fff; background-image: none; border-inline-end: 1px solid #eef1f4; --nav-hover: #f5f8fa; }
.nav__brand { gap: 10px; padding: 0 12px 32px; flex-shrink: 0; }
.nav__logo { width: 24px; height: 24px; background: none; border-radius: 0; color: #4fcce9; overflow: visible; }
.nav__logo svg { width: 23px; height: 23px; }
.nav__brandtext { min-width: 0; }
.nav__brand .nav__name { font-family: inherit; font-size: 18px; font-weight: 700; line-height: 1.3; white-space: normal; overflow-wrap: normal; }
:root:not([data-theme='dark']) .nav__brand .nav__name { color: #25272a; }
.nav__divider { display: none; }
.nav__group { gap: 0; flex-shrink: 0; }
.nav__group + .nav__group { margin-block-start: 14px; }
.nav__label { padding: 12px 14px 10px; margin: 0; font-size: 12px; font-weight: 600; letter-spacing: .08em; }
:root:not([data-theme='dark']) .nav__label { color: #858b90; }
.nav a, .nav .nav__parent { min-height: 42px; padding: 8px 14px; margin: 3px 0; gap: 12px; border-radius: 8px; font-size: 14px; font-weight: 400; line-height: 1.4; transition: background .2s ease, color .2s ease; }
:root:not([data-theme='dark']) .nav a,
:root:not([data-theme='dark']) .nav .nav__parent { color: #72787d; }
.nav .nav__icon { width: 20px; height: 20px; min-width: 20px; flex: none; }
:root:not([data-theme='dark']) .nav .nav__icon { color: inherit; }
.nav__icon svg { width: 20px; height: 20px; stroke-width: 1.8; }
.nav__text { min-width: 0; }
.nav .nav__chev, .nav .nav__chev svg { width: 16px; height: 16px; flex: none; }
.nav__chev { margin-inline-start: auto; }
@media (hover: hover) and (pointer: fine) { :root:not([data-theme='dark']) .nav a:hover, :root:not([data-theme='dark']) .nav .nav__parent:hover { background: #f5f8fa; color: #5b6064; } }
:root:not([data-theme='dark']) .nav a[aria-current='page'],
:root:not([data-theme='dark']) .nav .nav__parent--current,
:root[data-theme='dark'] .nav a[aria-current='page'],
:root[data-theme='dark'] .nav .nav__parent--current { background: #b9eaff; color: #253037; font-weight: 500; }
.nav__sub { margin-inline-start: 18px; margin-block: 7px 8px; padding-inline-start: 13px; border-inline-start: 3px solid #d5f2ff; gap: 0; }
.nav .nav__sub a { min-height: 34px; margin: 0; padding: 7px 0; padding-inline-start: 4px; font-size: 13.5px; border-radius: 0; }
:root:not([data-theme='dark']) .nav .nav__sub a[aria-current='page'] { color: #3f454a; background: none; font-weight: 500; }
:root[data-theme='dark'] .nav .nav__sub a[aria-current='page'] { color: #eef0f4; background: none; font-weight: 500; }
.nav .nav__signout { flex-shrink: 0; }
.nav__foot { margin-block-start: 20px; padding: 0; border: 0; border-radius: 0; flex-shrink: 0; }
:root:not([data-theme='dark']) .nav__foot,
:root[data-theme='dark'] .nav__foot { background: none; border: 0; }
.nav__foot .nav__label { padding-inline: 14px; }
.nav .langswitch { flex-wrap: wrap; }
.nav .langswitch button { padding-inline: 8px; }
@media (max-width: 800px) { .nav { width: 190px; } }
@media (prefers-reduced-motion: reduce) { .nav a, .nav .nav__parent { transition: none; } }

/* The reference's three pastel tints, its accent pill and its focus ring, as
   tokens. Every page below takes its colours from these instead of from the
   hex values themselves, so a palette (palette-ocean.css) restyles them all
   by redefining eleven names - none of them can be missed and left pastel. */
:root {
  --tint-1: #e5f7fe; --tint-1-ink: #42758a;
  --tint-2: #eeecff; --tint-2-ink: #665c98;
  --tint-3: #fff4d2; --tint-3-ink: #8e7733;
  --pill: #b7e9fb; --pill-ink: #2c424e;
  --focus-ring: #54c7ea;
}
:root[data-theme='dark'] {
  --tint-1: #293f4b; --tint-1-ink: #9ecfe0;
  --tint-2: #39354e; --tint-2-ink: #d6ccff;
  --tint-3: #3a3115; --tint-3-ink: #e0ce8c;
}

/* Dashboard composition from the supplied SchoolHub reference. */
.dashboard-home { --gap: 24px; --sky: var(--pill); --marigold: var(--tint-3); --coral: var(--tint-2); }
.dashboard-home .dash-attention { margin-block-end: var(--gap); }
.dashboard-home .dash-grid { grid-template-columns: minmax(0, 1fr) 340px; margin-block-start: 0; gap: 24px; }
.dashboard-home .dash-main, .dashboard-home .dash-rail { gap: 24px; }
.dashboard-home .tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; margin: 0; }
.dashboard-home .tile--fill { min-height: 158px; padding: 22px; border-radius: 20px; border: 0; }
.dashboard-home .tile--lavender { --tile-fill: var(--tint-2); }
.dashboard-home .tile--amber { --tile-fill: var(--tint-3); }
.dashboard-home .tile--fill::after { display: none; }
.dashboard-home .tile__value { font-family: inherit; font-size: 30px; font-weight: 700; color: #202124; margin-block-start: auto; }
.dashboard-home .tile__label { font-size: 16px; font-weight: 500; color: #35343a; }
.dashboard-home .tile__meta { font-size: 11px; color: #55545d; }
.dashboard-home .tile__trend { color: #148470; background: #fff; border-radius: 12px; }
.dashboard-home .dash-pair { grid-template-columns: minmax(230px, .85fr) minmax(0, 1.4fr); gap: 24px; }
.dashboard-home .dash-card { border-radius: 22px; border: 0; box-shadow: 0 10px 28px rgba(65,73,97,.04); overflow: hidden; }
.dashboard-home .card__head { padding: 24px 24px 16px; border: 0; }
.dashboard-home .card__title { font-family: inherit; font-size: 22px; font-weight: 700; letter-spacing: -.3px; }
.dashboard-home .card__body { padding: 8px 24px 24px; }
.dashboard-home .donut { width: 250px; }
.dashboard-home .donutwrap { gap: 20px; }
.dashboard-home .donutwrap .legend { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.dashboard-home .legend__item { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.dashboard-home .legend__item .legend__dot { width: 20px; height: 20px; }
.dashboard-home .legend__value { font-size: 22px; }
.dashboard-home .legend__label { margin-block-start: 5px; font-size: 12px; }
.dashboard-home .legend--row { margin-block-end: 28px; gap: 24px; }
.dashboard-home .legend__pill { font-size: 13px; }
.dashboard-home .chart--bars { min-height: 250px; max-height: 300px; }
.dashboard-home .dash-pair--wide { grid-template-columns: minmax(0, 1fr) 210px; }
.dashboard-home .dash-stat__value { font-family: inherit; font-size: 24px; overflow-wrap: anywhere; }
.dashboard-home .dash-stat__icon { background: #bdebf8; color: #fff; border-radius: 12px; width: 48px; height: 48px; }
.dashboard-home .dash-stat__label { font-size: 14px; font-weight: 500; }
.dashboard-home .dash-stat__meta { font-size: 12px; }
.dashboard-home .dash-calendar-agenda { background: var(--surface); border-radius: 22px; box-shadow: 0 10px 28px rgba(65,73,97,.04); overflow: hidden; }
.dashboard-home .dash-calendar-agenda .dash-card { box-shadow: none; border-radius: 0; }
.dashboard-home .calhead { gap: 8px; }
.dashboard-home .calhead .card__title { font-size: 22px; }
.dashboard-home .calhead .icon-btn { border: 1px solid var(--border-strong); border-radius: 7px; width: 27px; height: 27px; }
.dashboard-home .weekday { padding: 12px 2px; border-radius: 7px; }
.dashboard-home .weekday__name { font-size: 11px; }
.dashboard-home .weekday__num { margin-block-start: 10px; font-size: 18px; }
.dashboard-home button.weekday--now { background: #e8f8fd; color: var(--pill-ink); }
.dashboard-home .agenda { gap: 13px; max-height: 380px; overflow-y: auto; }
.dashboard-home .agenda__row { border: 0; border-radius: 9px; padding: 14px; min-height: 85px; background: var(--tint-2); color: #35343a; }
.dashboard-home .agenda__row--1 { background: #fff5cf; }
.dashboard-home .agenda__row--2 { background: var(--tint-1); }
.dashboard-home .agenda__time { padding-inline-end: 14px; border-inline-end: 3px solid white; align-self: stretch; display: flex; align-items: center; color: #35343a; }
.dashboard-home .agenda__meta { color: #65666a; }
.dashboard-home .agenda__what { font-size: 14px; }
.dashboard-home .dash-rail .dash-list { max-height: 420px; }
.dashboard-home .dash-payment { display: flex; align-items: center; gap: 12px; padding: 16px 0; border-block-end: 1px solid var(--border); }
.dashboard-home .dash-payment:last-child { border: 0; }
.dashboard-home .dash-payment__avatar { flex: none; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--pill); color: var(--pill-ink); font-weight: 600; }
.dashboard-home .dash-payment:nth-child(2n) .dash-payment__avatar { background: var(--tint-3); }
.dashboard-home .dash-payment__copy { flex: 1; min-width: 0; }
.dashboard-home .dash-payment__copy .strong { font-size: 14px; }
.dashboard-home .dash-payment__copy .subtle { font-size: 11px; margin-block-start: 3px; }
.dashboard-home .dash-payment__amount { font-size: 12px; white-space: nowrap; }
.dashboard-home .dash-trio { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dash-kids { display: flex; align-items: center; gap: 5px; }
.dash-kid { position: relative; width: 16px; height: 36px; color: #b9e9f8; }
.dash-kid::before { content: ''; position: absolute; width: 12px; height: 12px; border-radius: 50%; inset-inline-start: 2px; top: 0; background: currentColor; }
.dash-kid::after { content: ''; position: absolute; width: 16px; height: 22px; border-radius: 6px 6px 3px 3px; inset-inline-start: 0; top: 14px; background: currentColor; }
.dash-kid--yellow { color: #ffe170; }
:root:not([data-theme='dark']) .dashboard-home .dash-card,
:root:not([data-theme='dark']) .dashboard-home .dash-calendar-agenda { background: #fff; }
@media (max-width: 1450px) {
  .dashboard-home .dash-grid { grid-template-columns: minmax(0, 1fr); }
  .dashboard-home .dash-rail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}
@media (max-width: 800px) {
  .dashboard-home { --gap: 16px; }
  .dashboard-home .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .dashboard-home .tile--fill { min-height: 145px; padding: 20px; }
  .dashboard-home .dash-pair, .dashboard-home .dash-pair--wide, .dashboard-home .dash-trio, .dashboard-home .dash-rail { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .dashboard-home .dash-stack { flex-direction: row; }
  .dashboard-home .dash-stack > * { min-width: 0; }
  .dashboard-home .card__title { font-size: 20px; }
  .dashboard-home .dash-stat .card__body { padding: 18px; }
  .dashboard-home .dash-stat__value { font-size: 20px; }
}
.dashboard-home .tile__value { margin-block-start: 28px; }
.dashboard-home .tile__trend + .tile__value { margin-block-start: 0; }
.dashboard-home .chart--area path[fill='none'],
.dashboard-home .chart--area circle { stroke: #9edeee; }
.dashboard-home .chart--area path[fill='none'] { stroke-width: 4; }

/* Top controls and profile follow the supplied dashboard's rounded style. */
.appbar { padding-block: 24px 20px; }
.appbar__right { gap: 18px; flex-wrap: nowrap; }
.appbar__right > .icon-btn { width: 55px; height: 55px; flex: none; border: 0; border-radius: 50%; background: var(--surface); box-shadow: 0 10px 28px rgba(65,73,97,.04); color: var(--fg); }
.appbar__right > .icon-btn svg { width: 22px; height: 22px; }
.appbar__year { display: flex; align-items: center; gap: 8px; height: 55px; padding-inline: 16px 4px; border-radius: 28px; background: var(--surface); color: var(--fg-muted); box-shadow: 0 10px 28px rgba(65,73,97,.04); }
.appbar__calendar { display: flex; flex: none; }
.appbar__calendar svg { width: 20px; height: 20px; }
.appbar .appbar__year select { min-height: 0; height: 100%; padding-inline-start: 0; padding-inline-end: 28px; border: 0; border-radius: 28px; background-color: transparent; box-shadow: none; font-family: inherit; font-size: 15px; font-weight: 500; color: var(--fg); cursor: pointer; }
.appbar__year:focus-within { outline: 2px solid var(--sky-ink); outline-offset: 3px; }
.appbar .user-chip { gap: 16px; margin-inline-start: 18px; }
.appbar .user-chip__text { align-items: flex-end; text-align: end; line-height: 1.25; }
.appbar .user-chip__name { font-family: inherit; font-size: 18px; font-weight: 700; margin-block-end: 3px; max-width: 15rem; }
.appbar .user-chip__role { font-size: 14px; font-weight: 400; color: var(--fg-subtle); }
.appbar .user-chip__avatar { position: relative; overflow: visible; width: 52px; height: 52px; border: 4px solid var(--surface); background: linear-gradient(160deg,#99e4fb,#fde5a0); color: var(--pill-ink); font-size: 17px; }
.appbar .user-chip__avatar::after { content: ''; position: absolute; inset-inline-end: -3px; bottom: 0; width: 11px; height: 11px; border: 2px solid var(--surface); border-radius: 50%; background: #20b99a; }
@media (max-width: 760px) {
  .appbar { padding: 14px 16px; }
  .appbar__right { gap: 10px; }
  .appbar__right > .icon-btn { width: 44px; height: 44px; }
  .appbar__year { height: 44px; padding-inline-start: 10px; gap: 5px; }
  .appbar .user-chip { margin-inline-start: 0; }
  .appbar .user-chip__avatar { width: 44px; height: 44px; font-size: 14px; }
}

/* One page heading, aligned with the controls in the shared top bar. */
.appbar__left { flex: 1; }
.appbar__heading { min-width: 0; }
.appbar__heading h1 { margin: 0; font-size: var(--fs-lg); line-height: 1.25; }
.appbar__heading .page-head__sub { margin-block-start: 4px; line-height: 1.4; }
.page-head--actions { justify-content: flex-end; }
@media (max-width: 760px) {
  .appbar__left { flex-basis: 100%; }
  .appbar__right { margin-inline-start: auto; }
}
@media print {
  .appbar.no-print { display: block !important; position: static; padding: 0 0 16px; background: none; }
  .appbar .menu-toggle, .appbar .appbar__right { display: none !important; }
}

/* Attendance uses the same pastel cards and compact ledger as Finance. */
.attendance-page { --att-cyan: var(--pill); --att-yellow: var(--tint-3); --att-purple: var(--tint-2); }
.attendance-page .att-toolbar { padding: 18px 20px; background: var(--surface); border: 0; border-radius: 17px; gap: 18px; margin-block-end: 20px; align-items: flex-start; box-shadow: 0 2px 10px rgba(45,60,80,.025); }
.attendance-page .field { margin: 0; }
.attendance-page .field > label { font-size: 12px; font-weight: 500; color: var(--fg-muted); }
.attendance-page .att-toolbar select, .attendance-page .att-toolbar input { min-height: 38px; border-radius: 8px; background-color: var(--bg); border-color: transparent; font-size: 13px; box-shadow: none; }
.attendance-page .hint { font-size: 11px; margin-block-start: 6px; }
.attendance-page .att-tabs { margin-inline-start: auto; }
.attendance-page .att-tabs .row { gap: 4px; padding: 4px; border-radius: 12px; background: var(--bg); }
.attendance-page .att-tabs .btn { background: transparent; box-shadow: none; border: 0; border-radius: 8px; font-size: 12px; }
.attendance-page .att-tabs .btn[aria-pressed='true'] { background: var(--pill); color: var(--pill-ink); }
.att-summary { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 18px; margin-block-end: 20px; }
.att-stat { display: flex; flex-direction: column; gap: 8px; min-height: 140px; padding: 20px; border-radius: 18px; color: #25272a; background: var(--att-cyan); }
.att-stat--absent { background: #fde2ee; }
.att-stat--late { background: var(--att-yellow); }
.att-stat--excused { background: var(--att-purple); }
.attendance-page .att-stat--sick_leave { background-color: var(--tint-2); color: #25272a; }
.att-stat__dot { width: 10px; height: 10px; border-radius: 50%; background: rgba(255,255,255,.9); }
.att-stat__value { margin-block-start: 10px; font-size: 28px; line-height: 1; }
.att-stat__label { font-size: 13px; }
.attendance-page .card { border: 0; border-radius: 17px; box-shadow: 0 2px 10px rgba(45,60,80,.025); overflow: hidden; }
.attendance-page .card__head { padding: 18px 20px; border: 0; flex-wrap: wrap; gap: 12px; }
.attendance-page .card__title { font-family: inherit; font-size: 18px; }
.attendance-page .card__title .chip { font-family: inherit; font-size: 11px; background: var(--bg); color: var(--fg-muted); vertical-align: middle; }
.attendance-page .card__body { padding: 0 20px 18px; }
.attendance-page .btn { border-radius: 8px; font-size: 12px; }
.attendance-page .btn--primary { background: var(--pill); border-color: var(--pill); color: var(--pill-ink); box-shadow: none; }
.attendance-page .alert { border-radius: 9px; font-size: 12px; }
.att-roll-head { display: flex; justify-content: space-between; padding: 17px 16px; border-radius: 9px 9px 0 0; background: var(--tint-1); color: #42474b; font-size: 12px; }
.att-roll-head > :last-child { width: 330px; text-align: center; }
.attendance-page .roll { gap: 0; }
.attendance-page .roll__row { padding: 16px; min-height: 78px; border: 0; border-block-end: 1px solid var(--border); border-radius: 0; gap: 12px; background: transparent; }
.attendance-page .roll__row:focus-within { background: var(--coral-soft); }
.attendance-page .roll__row .avatar { width: 38px; height: 38px; font-size: 12px; background: var(--tint-1); color: var(--tint-1-ink); }
.attendance-page .roll__row .strong { font-size: 13px; font-weight: 500; }
.attendance-page .roll__row .subtle { font-size: 11px; }
.attendance-page .statuspicker { padding: 0; gap: 6px; background: none; flex-wrap: wrap; }
.attendance-page .statuspicker button { min-height: 34px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); color: var(--fg-muted); padding: 6px 12px; font-size: 12px; font-weight: 500; }
.attendance-page .statuspicker button[aria-pressed='true'] { box-shadow: inset 0 0 0 1px currentColor; }
.attendance-page .statuspicker button[data-s='present'][aria-pressed='true'] { background: var(--tint-1); color: var(--tint-1-ink); border-color: var(--focus-ring); }
.attendance-page .statuspicker button[data-s='absent'][aria-pressed='true'] { background: #fde2ee; color: #c2185b; border-color: #f72585; }
.attendance-page .statuspicker button[data-s='late'][aria-pressed='true'] { background: var(--tint-3); color: var(--tint-3-ink); border-color: var(--tint-3-ink); }
.attendance-page .statuspicker button[data-s='excused'][aria-pressed='true'] { background: var(--tint-2); color: var(--tint-2-ink); border-color: var(--tint-2); }
.attendance-page .tablewrap { box-shadow: none; }
.attendance-page thead th { background: var(--tint-1); color: #42474b; font-size: 12px; }
.attendance-page tbody td { font-size: 13px; border-color: var(--border); }
:root[data-theme='dark'] .attendance-page .att-roll-head,
:root[data-theme='dark'] .attendance-page thead th { background: var(--surface-alt); color: var(--fg); }
@media (max-width: 800px) {
  .att-summary { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 14px; }
  .attendance-page .att-tabs { flex-basis: 100%; margin-inline-start: 0; }
  .attendance-page .roll__row { flex-wrap: wrap; }
  .attendance-page .statuspicker { flex-basis: 100%; padding-inline-start: 50px; }
  .att-roll-head > :last-child { width: auto; }
}
@media (max-width: 420px) {
  .attendance-page .statuspicker { padding-inline-start: 0; }
  .attendance-page .statuspicker button { flex: 1 1 40%; }
  .attendance-page .att-toolbar .field { min-width: 0; max-width: 100%; }
}

/* Equal sizing for the roll counter and header actions. */
.attendance-page .att-roll-card > .card__head { align-items: center; }
.attendance-page .att-roll-card > .card__head .card__title { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.attendance-page .att-roll-card > .card__head .row { gap: 10px; }
.attendance-page .att-roll-card > .card__head .chip,
.attendance-page .att-roll-card > .card__head .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 38px;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  box-shadow: none;
}
.attendance-page .att-roll-card > .card__head .btn--primary { border-color: var(--pill); }
.attendance-page .att-roll-card > .card__head .btn { min-width: 80px; }

/* Shared action sizing across office pages and their dialogs. */
:root {
  --action-height: 38px;
  --action-radius: 8px;
  --action-gap: 10px;
}
.main .btn,
.modal .btn,
.card__head .chip,
.card__head .badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: var(--action-height);
  min-height: var(--action-height);
  padding: 0 14px;
  border-width: 1px;
  border-style: solid;
  border-radius: var(--action-radius);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  box-shadow: none;
}
.main .btn, .modal .btn { min-width: 80px; }
.main .card__head { align-items: center; flex-wrap: wrap; gap: var(--action-gap); }
.main .card__head .row,
.main .page-head__actions,
.modal__foot { gap: var(--action-gap); }
.main .card__title:has(.chip, .badge) { display: flex; align-items: center; flex-wrap: wrap; gap: var(--action-gap); }

/* Compact top-bar controls, aligned with the profile. */
.appbar__right > .icon-btn { width: 44px; height: 44px; }
.appbar__right > .icon-btn svg { width: 19px; height: 19px; }
.appbar__year { height: 44px; padding-inline: 12px 4px; gap: 6px; border-radius: 22px; }
.appbar__calendar svg { width: 18px; height: 18px; }
.appbar .appbar__year select { font-size: 14px; }

/* Sign-in uses the same light surfaces and pastel palette as the office. */
.login-page {
  background: var(--bg);
  background-image: radial-gradient(ellipse at 10% 15%, rgba(191,238,254,.3), transparent 50%), radial-gradient(ellipse at 90% 85%, rgba(200,196,255,.24), transparent 50%);
  padding: 32px;
  --login-accent-text: var(--fg);
  --login-accent-soft: #54b9d8;
}
.login-layout { width: min(100%, 1040px); display: grid; grid-template-columns: 1.08fr 1fr; background: var(--surface); border: 1px solid var(--border); border-radius: 28px; overflow: hidden; box-shadow: 0 18px 55px rgba(58,78,105,.08); }
.login-welcome { display: flex; flex-direction: column; padding: 38px; background: #e9f7fc; color: #25272a; }
.login-brand { display: flex; align-items: center; gap: 12px; font-size: 20px; font-weight: 700; }
.login-brand__mark { width: 32px; height: 32px; display: flex; color: #35a9cd; }
.login-brand__mark svg { width: 100%; height: 100%; }
.login-welcome__copy { margin-block-start: 62px; }
.login-eyebrow { color: #526c78; font-size: 12px; margin-block-end: 14px; }
.login-welcome h2 { font-family: inherit; font-size: clamp(27px, 3vw, 38px); line-height: 1.25; letter-spacing: -.7px; max-width: 370px; margin-block-end: 18px; }
.login-welcome p { color: #536571; font-size: 15px; line-height: 1.8; max-width: 350px; }
.login-art { margin-block: 20px 14px; }
.login-art svg { width: 100%; display: block; }
.login-card { max-width: 460px; padding: 40px; border: 1px solid var(--border); border-radius: 22px; background: var(--surface); color: var(--fg); backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: 0 10px 28px rgba(65,73,97,.04); }
.login-layout .login-card { max-width: none; border: 0; border-radius: 0; box-shadow: none; padding: 46px 40px; align-self: center; }
.login-card__eyebrow { font-size: 12px; color: var(--fg-muted); margin-block-end: 12px; }
.login-card h1 { font-family: inherit; font-size: 28px; text-align: start; color: var(--fg); margin-block-end: 10px; }
.login-card .sub { text-align: start; color: var(--fg-muted); font-size: 14px; margin-block-end: 26px; }
.login-card .gfield > input { color: var(--fg); height: 52px; caret-color: var(--fg); }
.login-card .gfield > input:-webkit-autofill, .login-card .gfield > input:-webkit-autofill:focus { -webkit-text-fill-color: var(--fg); caret-color: var(--fg); }
@media (hover: hover) and (pointer: fine) { .login-card .gfield > input:-webkit-autofill:hover { -webkit-text-fill-color: var(--fg); caret-color: var(--fg); } }
.login-card .gfield__outline { border: 1px solid var(--border-strong); border-radius: 10px; }
@media (hover: hover) and (pointer: fine) { .login-card .gfield:hover .gfield__outline { border-color: var(--fg-muted); } }
.login-card .gfield__label,
.login-card .gfield > input:not(:placeholder-shown) ~ .gfield__label { color: var(--fg-muted); }
.login-card .gfield > input:focus ~ .gfield__label { color: var(--fg); }
.login-card .gfield > input:focus ~ .gfield__outline { border-color: #35a9cd; }
.login-card .gfield__reveal { color: var(--fg-muted); }
@media (hover: hover) and (pointer: fine) { .login-card .gfield__reveal:hover { color: var(--fg); background: var(--surface-alt); } }
.login-card .login-link { color: var(--fg-muted); font-size: 12px; font-weight: 500; }
.login-card .btn--login { min-height: 44px; border: 1px solid #b9eaff; border-radius: 8px; background: #b9eaff; color: #253037; box-shadow: none; font-size: 14px; font-weight: 600; }
@media (hover: hover) and (pointer: fine) { .login-card .btn--login:hover:not(:disabled) { background: #a7e2f8; box-shadow: none; } }
.login-card .btn--glass { min-height: 44px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--fg); font-size: 13px; font-weight: 500; white-space: normal; text-align: center; }
@media (hover: hover) and (pointer: fine) { .login-card .btn--glass:hover { background: var(--surface-alt); color: var(--fg); } }
.login-card .login-or, .login-card .login-foot { color: var(--fg-muted); font-size: 12px; }
.login-card .login-or::before, .login-card .login-or::after { background: var(--border); }
.login-card .segmented label { background: var(--surface-alt); border-color: transparent; color: var(--fg-muted); font-size: 12px; padding: 9px 10px; }
.login-card .segmented label::before { display: none; }
.login-card .segmented input:checked + label { background: #e6f8ff; border-color: #b9eaff; color: #253037; }
.login-card .label { color: var(--fg-muted); }
.login-card .icon-btn { width: 38px; height: 38px; border-radius: 50%; background: var(--surface-alt); border: 0; color: var(--fg); }
@media (hover: hover) and (pointer: fine) { .login-card .icon-btn:hover { background: var(--border); } }
.login-card .alert--error { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.login-card .alert--warn { background: var(--warning-soft); border-color: var(--warning); color: var(--warning-ink); }
:root[data-theme='dark'] .login-welcome { background: #293b48; color: #eef0f4; }
:root[data-theme='dark'] .login-welcome p,
:root[data-theme='dark'] .login-eyebrow { color: #c0d2dc; }
@media (max-width: 800px) {
  .login-page { padding: 20px; }
  .login-layout { max-width: 460px; grid-template-columns: 1fr; }
  .login-welcome { padding: 24px 28px; }
  .login-welcome__copy, .login-art { display: none; }
  .login-layout .login-card { padding: 28px; }
}
@media (max-width: 380px) {
  .login-page { padding: 12px; }
  .login-layout .login-card { padding: 24px 20px; }
  .login-card .segmented label { padding-inline: 8px; }
}
:root:not([data-theme='dark']) .login-page,
:root[data-theme='dark'] .login-page {
  --login-accent-text: var(--fg);
  --login-accent-soft: #54b9d8;
  background-color: var(--bg);
  background-image: radial-gradient(ellipse at 10% 15%, rgba(191,238,254,.3), transparent 50%), radial-gradient(ellipse at 90% 85%, rgba(200,196,255,.24), transparent 50%);
}

/* Student directory and files share the dashboard's quiet, pastel surfaces. */
.students-page .card { border: 1px solid var(--border); border-radius: 22px; box-shadow: none; overflow: hidden; }
.students-page .card__head { padding: 20px 24px; background: var(--surface); border-bottom: 1px solid var(--border); }
.students-page .card__body { padding: 24px; }
.students-page .card__title { font-size: 16px; font-weight: 600; }
.students-page .students-directory > .toolbar { margin: 0; padding: 24px; gap: 16px; background: var(--surface); border: 0; border-bottom: 1px solid var(--border); border-radius: 0; align-items: end; }
.students-page .toolbar .field { flex: 1 1 180px; min-width: 0; }
.students-page .toolbar .field--wide { flex: 2 1 280px; }
.students-page .toolbar label { font-size: 12px; color: var(--fg-muted); font-weight: 500; }
.students-page .toolbar input, .students-page .toolbar select { height: 42px; border: 1px solid var(--border); border-radius: 10px; background-color: var(--surface); font-size: 13px; }
.students-results__head { display: flex; align-items: center; gap: 10px; padding: 18px 24px; font-size: 13px; }
.students-count { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 28px; padding-inline: 10px; border-radius: 8px; background: var(--tint-2); color: var(--tint-2-ink); font-weight: 600; }
.students-page .tablewrap { border: 0; border-radius: 0; box-shadow: none; }
.students-page thead th { padding: 15px 24px; background: var(--tint-1); color: #42474b; font-size: 12px; font-weight: 500; border-bottom: 1px solid var(--border); }
.students-page tbody td { padding: 16px 24px; font-size: 13px; border-color: var(--border); }
.students-page .table--tight td { padding: 12px 10px; }
.students-directory tbody tr:last-child td { border-bottom: 0; }
@media (hover: hover) and (pointer: fine) { .students-directory tbody tr:hover { background: var(--surface-alt); } }
.student-name { display: inline-flex; align-items: center; gap: 12px; color: var(--fg); font-weight: 600; text-decoration: none; }
.student-name:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 5px; border-radius: 5px; }
.student-avatar { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 36px; width: 36px; height: 36px; border-radius: 50%; background: var(--tint-2); color: var(--tint-2-ink); font-size: 14px; }
.students-directory tr:nth-child(3n+2) .student-avatar { background: #fff1cc; color: #023047; }
.students-directory tr:nth-child(3n) .student-avatar { background: #e6f4fa; color: #00719c; }
.student-class { display: inline-flex; align-items: center; min-height: 28px; padding: 4px 10px; border-radius: 8px; background: var(--surface-alt); white-space: nowrap; }
:root[data-theme='dark'] .students-page thead th { background: var(--surface-alt); color: var(--fg); }
:root[data-theme='dark'] .students-count, :root[data-theme='dark'] .student-avatar { background: var(--tint-2); color: var(--tint-2-ink); }
:root[data-theme='dark'] .students-directory tr:nth-child(3n+2) .student-avatar { background: var(--tint-3); color: var(--tint-3-ink); }
:root[data-theme='dark'] .students-directory tr:nth-child(3n) .student-avatar { background: var(--tint-1); color: var(--tint-1-ink); }
@media (max-width: 640px) {
  .students-page .students-directory > .toolbar, .students-page .card__head, .students-page .card__body { padding: 18px; }
  .students-page .toolbar .field--wide { flex-basis: 100%; }
  .students-page thead th, .students-page tbody td { padding-inline: 16px; }
  .students-results__head { padding-inline: 18px; }
}

/* Student list reference: compact card, cyan checks and lavender selection. */
.students-page .students-directory { border-radius: 14px; padding: 18px 18px 0; }
.students-directory__header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 14px; margin-bottom: 15px; }
.students-directory__header h2 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.15px; }
.students-table-search { width: 210px; height: 32px; border: 1px solid var(--border); border-radius: 16px; display: flex; align-items: center; gap: 7px; padding-inline: 11px; color: var(--fg-muted); }
.students-table-search > span { display: flex; }
.students-table-search svg { width: 14px; height: 14px; }
.students-table-search input { width: 100%; min-width: 0; height: 100%; padding: 0; border: 0; border-radius: 0; background: transparent; font-size: 11px; box-shadow: none; }
.students-table-search:focus-within { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.students-table-search input:focus { outline: none; box-shadow: none; }
.students-page .students-directory > .toolbar { padding: 0 0 12px; gap: 12px; border: 0; }
.students-directory .toolbar .field { flex: 0 1 190px; }
.students-page .students-directory .toolbar select { height: 34px; font-size: 12px; border-radius: 8px; }
.students-directory .students-results__head { padding: 0 0 14px; font-size: 11px; }
.students-directory .students-count { height: 24px; min-width: 28px; font-size: 11px; }
.students-directory .tablewrap { border-radius: 6px 6px 0 0; overflow-x: auto; }
.students-directory table { min-width: 860px; width: 100%; }
.students-page .students-directory thead th { height: 50px; padding: 0 10px; background: var(--tint-1); color: #697078; font-size: 12px; }
.students-page .students-directory tbody td { height: 68px; padding: 8px 10px; font-size: 12px; }
.students-directory tbody tr { cursor: pointer; }
.students-page .students-directory .student-select-cell { width: 34px; text-align: center; padding-inline: 8px 2px; }
.students-directory th:nth-child(2) { min-width: 200px; }
.students-directory th:last-child { min-width: 180px; }
.students-directory .student-name { gap: 10px; font-weight: 500; }
.students-directory .student-avatar { width: 33px; height: 33px; flex-basis: 33px; object-fit: cover; }
.student-meta { display: flex; flex-direction: column; min-width: 0; }
.student-meta__name { line-height: 1.2; }
.student-meta__detail { font-size: 10px; color: var(--fg-muted); margin-top: 4px; font-weight: 400; }
.student-dob { display: inline-block; min-width: 96px; padding: 7px 14px; background: var(--surface-alt); border-radius: 16px; color: var(--fg-muted); text-align: center; white-space: nowrap; }
.students-directory .student-address { line-height: 1.55; white-space: normal; max-width: 220px; }
.students-directory .student-check { appearance: none; -webkit-appearance: none; width: 14px; height: 14px; min-height: 0; padding: 0; border: 1px solid #cfd3d8; border-radius: 4px; background: var(--surface); margin: 0; display: inline-grid; place-items: center; cursor: pointer; vertical-align: middle; }
.students-directory .student-check:checked, .students-directory .student-check:indeterminate { background: var(--focus-ring); border-color: var(--focus-ring); }
.students-directory .student-check:checked::after { content: '✓'; color: #fff; font-size: 10px; line-height: 1; font-weight: 700; }
.students-directory .student-check:indeterminate::after { content: '−'; color: #fff; font-size: 12px; line-height: 1; }
.students-directory tbody tr.selected { background: #efedff; }
@media (hover: hover) and (pointer: fine) { .students-directory tbody tr.selected:hover { background: #efedff; } }
:root[data-theme='dark'] .students-directory tbody tr.selected { background: var(--tint-2); }
:root[data-theme='dark'] .students-page .students-directory thead th { background: var(--surface-alt); color: var(--fg); }
@media (max-width: 640px) {
  .students-page .students-directory { padding: 14px 12px 0; }
  .students-table-search { width: 100%; }
  .students-directory .toolbar .field { flex: 1 1 120px; }
}
.students-page .students-directory .toolbar select { padding-block: 0; padding-inline-start: 12px; line-height: normal; }

/* Student profile: an identity banner, readable facts and pastel fee totals. */
.student-profile .profile-overview { margin-bottom: 22px; padding: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: 20px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 24px; border-top: 5px solid var(--pill); }
.profile-overview__identity { display: flex; align-items: center; gap: 20px; }
.profile-overview__identity > .row { margin: 0; flex-direction: column; gap: 10px; }
.student-profile .avatar--xl { width: 78px; height: 78px; background: var(--tint-2); color: var(--tint-2-ink); border: 4px solid var(--surface); box-shadow: 0 0 0 1px var(--border); }
.profile-eyebrow { color: var(--fg-muted); font-size: 11px; margin-bottom: 6px; }
.profile-overview h2 { margin: 0 0 8px; font-size: 24px; font-weight: 600; }
.profile-overview p { margin: 0; font-size: 12px; }
.profile-highlights { display: flex; flex-wrap: wrap; gap: 12px; margin: 0; }
.profile-highlights .profile-fact { padding: 14px 18px; min-width: 108px; border-radius: 12px; background: var(--tint-1); }
.profile-highlights .profile-fact:nth-child(2) { background: var(--tint-2); }
.profile-highlights .profile-fact:nth-child(3) { background: var(--tint-3); }
.profile-fact dt { margin: 0 0 7px; color: var(--fg-muted); font-size: 11px; font-weight: 400; }
.profile-fact dd { margin: 0; color: var(--fg); font-size: 14px; font-weight: 500; overflow-wrap: anywhere; }
.profile-columns { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr); gap: 22px; align-items: start; }
.student-profile .card { border-radius: 18px; }
.student-profile .card__head { padding: 18px 22px; }
.student-profile .card__title { font-size: 14px; }
.student-profile .card__body { padding: 22px; }
.profile-facts { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 22px 28px; margin: 0; }
.student-profile .accesscode { margin: 24px 0 0; padding: 16px; border: 1px solid #e0dcf7; border-radius: 12px; background: #f3f1ff; flex-wrap: wrap; gap: 12px; }
.student-profile .accesscode .strong { color: var(--tint-2-ink); }
.student-profile .card__foot { display: flex; flex-wrap: wrap; gap: 10px; padding: 16px 22px; background: var(--surface); }
.student-profile .btn--primary { background: var(--pill); border-color: var(--pill); color: var(--pill-ink); }
.student-profile .btn--danger { background: #fff0f3; border-color: #f6d7df; color: #b6304d; }
.profile-fee-summary { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 16px; margin: 22px 22px 0; }
.profile-fee-summary .profile-fact { background: var(--tint-2); padding: 20px; border-radius: 14px; }
.profile-fee-summary .profile-fact:nth-child(2) { background: var(--tint-1); }
.profile-fee-summary .profile-fact:nth-child(3) { background: var(--tint-3); }
.profile-fee-summary dd { font-size: 22px; font-weight: 600; }
.student-profile .profile-danger { border-color: #f0dfe3; }
.student-profile .profile-danger .card__body { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; }
.profile-danger p { flex: 1 1 350px; margin: 0; font-size: 12px; }
:root[data-theme='dark'] .profile-highlights .profile-fact, :root[data-theme='dark'] .profile-fee-summary .profile-fact { background: var(--tint-2); }
:root[data-theme='dark'] .profile-highlights .profile-fact:nth-child(2), :root[data-theme='dark'] .profile-fee-summary .profile-fact:nth-child(2) { background: var(--tint-1); }
:root[data-theme='dark'] .profile-highlights .profile-fact:nth-child(3), :root[data-theme='dark'] .profile-fee-summary .profile-fact:nth-child(3) { background: var(--tint-3); }
:root[data-theme='dark'] .student-profile .accesscode { background: var(--tint-2); border-color: #52496e; }
:root[data-theme='dark'] .student-profile .accesscode .strong { color: var(--tint-2-ink); }
:root[data-theme='dark'] .student-profile .btn--danger { background: #462e38; border-color: #69404b; color: #ffbacb; }
@media (max-width: 1000px) { .profile-columns { grid-template-columns: 1fr; } }
@media (max-width: 600px) {
  .student-profile .profile-overview { padding: 18px; }
  .profile-highlights { width: 100%; }
  .profile-highlights .profile-fact { flex: 1 1 100px; min-width: 0; }
  .profile-fee-summary { grid-template-columns: 1fr; }
  .profile-facts { gap: 20px 16px; }
  .profile-overview__identity { gap: 14px; }
  .profile-overview h2 { font-size: 20px; }
}

/* Paired actions share the width of the longest label, in every office view.
   Dialog footers are left out: forms.css keeps their buttons at natural width. */
:is(.main, .modal) :is(.card__foot, .page-head__actions, .row):has(> .btn):not(:has(> :not(.btn, .sr-only, [hidden], input[type="hidden"]))) {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--action-gap);
  align-items: stretch;
}
:is(.main, .modal) :is(.card__foot, .page-head__actions, .row):has(> .btn):not(:has(> :not(.btn, .sr-only, [hidden], input[type="hidden"]))) > .btn {
  width: 100%;
  min-width: max-content;
  height: var(--action-height);
  min-height: var(--action-height);
  padding: 0 14px;
  border-width: 1px;
  border-radius: var(--action-radius);
  font-size: 12px;
  line-height: 1;
}
@media (max-width: 600px) {
  :is(.main, .modal) :is(.card__foot, .page-head__actions, .row):has(> .btn):not(:has(> :not(.btn, .sr-only, [hidden], input[type="hidden"]))) {
    grid-auto-flow: row;
    grid-template-columns: 1fr;
  }
}

/* Classes: classroom icons and the shared cyan/lavender/yellow palette. */
.classes-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr)); gap: 22px; }
.classes-page .card { border: 1px solid var(--border); border-radius: 18px; overflow: hidden; box-shadow: none; }
.classes-page .card__head { padding: 20px; background: var(--surface); }
.classes-page .card__body { padding: 20px; }
.classes-page .card__title { font-size: 15px; font-weight: 600; }
.class-card { --class-tint: var(--tint-1); --class-ink: var(--tint-1-ink); }
.class-card:nth-child(3n+2) { --class-tint: var(--tint-2); --class-ink: var(--tint-2-ink); }
.class-card:nth-child(3n) { --class-tint: var(--tint-3); --class-ink: var(--tint-3-ink); }
.classes-page .class-card .card__head { background: var(--class-tint); border-bottom: 0; gap: 12px; }
.class-card__identity { display: flex; align-items: center; gap: 12px; }
.class-card__icon { width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center; color: var(--class-ink); background: var(--surface); }
.class-card__icon svg { width: 24px; height: 24px; }
.class-card .card__title a, .class-student-link { color: var(--fg); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .class-card .card__title a:hover, .class-student-link:hover { text-decoration: underline; } }
.classes-page .class-card .card__head .chip { height: 28px; min-height: 28px; padding: 0 10px; background: var(--surface); border: 0; font-size: 11px; border-radius: 14px; }
.class-card .card__body { display: grid; gap: 20px; font-size: 13px; }
.class-card .row { margin: 0; }
.class-card__capacity-label { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.class-capacity { height: 7px; margin-top: 12px; overflow: hidden; background: var(--surface-alt); border-radius: 5px; }
.class-capacity span { display: block; height: 100%; border-radius: inherit; background: var(--class-ink); opacity: .65; }
.class-card .chip { font-size: 12px; background: var(--class-tint); color: var(--fg); border: 0; border-radius: 8px; }
.class-detail-grid { display: grid; grid-template-columns: minmax(0,1.6fr) minmax(0,1fr); gap: 22px; align-items: start; }
.classes-page .tablewrap { border: 0; box-shadow: none; border-radius: 0; }
.classes-page thead th { background: var(--tint-1); font-size: 12px; color: var(--fg-muted); padding: 16px; }
.classes-page tbody td { padding: 16px; font-size: 13px; }
.classes-page .btn--primary { background: var(--pill); border-color: var(--pill); color: var(--pill-ink); }
:root[data-theme='dark'] .class-card { --class-tint: var(--tint-1); --class-ink: var(--tint-1-ink); }
:root[data-theme='dark'] .class-card:nth-child(3n+2) { --class-tint: var(--tint-2); --class-ink: var(--tint-2-ink); }
:root[data-theme='dark'] .class-card:nth-child(3n) { --class-tint: var(--tint-3); --class-ink: var(--tint-3-ink); }
:root[data-theme='dark'] .classes-page thead th { background: var(--surface-alt); }
@media (max-width: 1000px) { .class-detail-grid { grid-template-columns: 1fr; } }
.classes-page .card__head .badge { background: var(--tint-2); color: var(--tint-2-ink); border-color: transparent; height: 30px; min-height: 30px; padding-inline: 11px; }
:root[data-theme='dark'] .classes-page .card__head .badge { background: var(--tint-2); color: var(--tint-2-ink); }
@media (max-width: 1100px) { .class-detail-grid { grid-template-columns: 1fr; } }

/* Marks workspace follows the same pastel surfaces as Students and Classes. */
.marks-page .toolbar { padding: 20px 24px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); gap: 18px; margin-bottom: 20px; }
.marks-page .toolbar .field { flex: 1 1 220px; min-width: 0; max-width: 360px; }
.marks-page .toolbar label { font-size: 12px; font-weight: 500; color: var(--fg-muted); }
.marks-page .toolbar select { height: 42px; padding-block: 0; border: 1px solid var(--border); border-radius: 10px; font-size: 13px; background-color: var(--surface); }
.marks-summary { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 18px; margin: 0 0 22px; }
.marks-summary__item { border-radius: 16px; padding: 20px 24px; background: var(--tint-2); }
.marks-summary__item:nth-child(2) { background: var(--tint-1); }
.marks-summary__item:nth-child(3) { background: var(--tint-3); }
.marks-summary dt { font-size: 12px; color: var(--fg-muted); margin-bottom: 10px; }
.marks-summary dd { margin: 0; font-size: 24px; font-weight: 600; color: var(--fg); }
.marks-summary__item:last-child dd { font-size: 18px; line-height: 1.5; }
.marks-page .card { border: 1px solid var(--border); border-radius: 18px; overflow: hidden; box-shadow: none; }
.marks-page .card__head { padding: 20px 24px; background: var(--surface); }
.marks-page .card__title { font-size: 15px; font-weight: 600; }
.marks-page .btn--primary { background: var(--pill); border-color: var(--pill); color: var(--pill-ink); }
.marks-page .markgrid thead th { background: var(--tint-1); color: var(--fg); font-size: 12px; font-weight: 500; padding: 16px; min-width: 128px; text-align: center; }
.marks-page .markgrid thead th.sticky-name { background: var(--tint-1); text-align: start; }
.marks-page .markgrid .sticky-name { min-width: 210px; }
.marks-page .markgrid tbody td { padding: 14px 16px; }
.marks-page .sticky-name > .subtle { margin-top: 7px; font-size: 11px; }
.marks-student { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.marks-avatar { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--tint-2); color: var(--tint-2-ink); font-size: 12px; flex-shrink: 0; }
.marks-page .cell-stack { flex-direction: column; gap: 7px; }
.marks-page .markgrid input[type='text'] { width: 72px; height: 36px; padding: 0 8px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); font-size: 13px; }
.marks-page .markgrid input[type='text']:focus { border-color: var(--focus-ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus-ring) 14%, transparent); }
.marks-page .markgrid input.invalid { border-color: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }
.marks-page .markgrid input[type='text']:disabled { background: var(--surface-alt); border-style: dashed; }
.marks-page .mini-check { font-size: 10px; font-weight: 400; }
.marks-page .mini-check input { accent-color: var(--focus-ring); width: 14px; height: 14px; }
.marks-page .markgrid td.absent-cell { background: var(--danger-soft); }
.marks-page .alert { border-radius: 12px; font-size: 13px; }
:root[data-theme='dark'] .marks-summary__item { background: var(--tint-2); }
:root[data-theme='dark'] .marks-summary__item:nth-child(2) { background: var(--tint-1); }
:root[data-theme='dark'] .marks-summary__item:nth-child(3) { background: var(--tint-3); }
:root[data-theme='dark'] .marks-page .markgrid thead th { background: var(--tint-1); }
:root[data-theme='dark'] .marks-avatar { background: var(--tint-2); color: var(--tint-2-ink); }
@media (max-width: 640px) {
  .marks-summary { gap: 10px; }
  .marks-summary__item { padding: 16px 12px; }
  .marks-summary dd { font-size: 20px; }
  .marks-summary__item:last-child dd { font-size: 14px; }
  .marks-page .toolbar, .marks-page .card__head { padding: 18px; }
  .marks-page .markgrid .sticky-name { min-width: 165px; }
}

/* Staff directory and profile share the student workspace's visual language. */
.staff-page .card { border: 1px solid var(--border); border-radius: 18px; box-shadow: none; overflow: hidden; }
.staff-page .tablewrap { border: 0; border-radius: 0; box-shadow: none; }
.staff-directory table { min-width: 850px; }
.staff-status-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; margin-block-end: 20px; }
.staff-stat--active { background: var(--pill); }
.staff-stat--on_leave { background: var(--tint-3); }
.staff-stat--sick_leave { background: var(--tint-2); }
.staff-stat--inactive { background: #e8ebf0; }
.staff-status-list .card__head { flex-wrap: wrap; gap: 12px; padding: 20px; }
.staff-status-list .card__body { padding: 0 20px; }
.staff-status-row { display: flex; align-items: center; gap: 12px; padding: 18px 0; border-block-end: 1px solid var(--border); }
.staff-status-row:last-child { border-block-end: 0; }
.staff-status-row .avatar { flex: 0 0 38px; width: 38px; height: 38px; font-size: 12px; }
.staff-status-person { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.staff-status-person > .subtle { display: block; margin-block-start: 4px; font-size: 12px; }
.staff-status-details { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-block-start: 6px; font-size: 11px; color: var(--fg-muted); }
.staff-status-picker { flex-shrink: 0; gap: 6px; }
.staff-status-picker button { min-height: 38px; min-width: 82px; padding: 6px 12px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); color: var(--fg-muted); font-size: 12px; font-weight: 500; }
.staff-status-picker button[aria-pressed='true'] { background: var(--primary-soft); color: var(--fg); border-color: var(--border-strong); box-shadow: inset 0 0 0 1px currentColor; }
.staff-status-picker button[data-s='active'][aria-pressed='true'] { background: var(--tint-1); color: var(--tint-1-ink); }
.staff-status-picker button[data-s='on_leave'][aria-pressed='true'] { background: var(--tint-3); color: var(--tint-3-ink); }
.staff-status-picker button[data-s='sick_leave'][aria-pressed='true'] { background: var(--tint-2); color: var(--tint-2-ink); }
.staff-status-picker button:disabled { cursor: wait; opacity: .65; }
@media (max-width: 1100px) {
  .staff-status-row { flex-wrap: wrap; }
  .staff-status-picker { flex-basis: 100%; margin-inline-start: 50px; }
}
@media (max-width: 600px) {
  .staff-status-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .staff-status-picker { margin-inline-start: 0; }
  .staff-status-picker button { flex: 1 1 40%; min-width: 0; }
}
@media (pointer: coarse) { .staff-status-picker button { min-height: 44px; } }
.staff-page thead th { background: var(--tint-1); color: var(--fg-muted); padding: 18px; font-size: 12px; font-weight: 500; }
.staff-page tbody td { padding: 18px; font-size: 13px; }
.staff-page .avatar { background: var(--tint-2); color: var(--tint-2-ink); }
.staff-directory tr:nth-child(3n+2) .avatar { background: var(--tint-3); color: var(--tint-3-ink); }
.staff-directory tr:nth-child(3n) .avatar { background: var(--tint-1); color: var(--tint-1-ink); }
.staff-name { color: var(--fg); text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .staff-name:hover { text-decoration: underline; } }
.staff-directory td:first-child .subtle { display: block; margin-top: 4px; font-size: 11px; }
.staff-directory .chip { border-radius: 10px; font-size: 11px; padding: 6px 10px; }
.staff-page .btn--primary { background: var(--pill); border-color: var(--pill); color: var(--pill-ink); }
.staff-assignment-list { display: grid; gap: 12px; }
.staff-assignment { display: grid; gap: 6px; padding: 16px; border-radius: 12px; background: var(--tint-1); color: var(--fg); text-decoration: none; font-size: 13px; }
.staff-assignment:nth-child(3n+2) { background: var(--tint-2); }
.staff-assignment:nth-child(3n) { background: var(--tint-3); }
@media (hover: hover) and (pointer: fine) { .staff-assignment:hover { box-shadow: inset 0 0 0 1px var(--border-strong); } }
.staff-assignment__year { font-size: 11px; color: var(--fg-muted); }
.staff-page .profile-highlights .profile-fact { max-width: 240px; }
.staff-page .profile-facts .profile-fact:last-child { min-width: 0; }
:root[data-theme='dark'] .staff-page thead th { background: var(--tint-1); }
:root[data-theme='dark'] .staff-page .avatar { background: var(--tint-2); color: var(--tint-2-ink); }
:root[data-theme='dark'] .staff-assignment { background: var(--tint-1); }
:root[data-theme='dark'] .staff-assignment:nth-child(3n+2) { background: var(--tint-2); }
:root[data-theme='dark'] .staff-assignment:nth-child(3n) { background: var(--tint-3); }

/* Destructive actions keep a clear warning tone without a solid red fill. */
.btn.btn--danger {
  background: #fff0f3;
  border: 1px solid #f2d4dd;
  color: #a83c58;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) { .btn.btn--danger:hover:not(:disabled) {
  background: #fbe3eb;
  border-color: #e9bbca;
  color: #92304a;
  opacity: 1;
} }
:root[data-theme='dark'] .btn.btn--danger {
  background: #3d1428;
  border-color: #664250;
  color: #ffb3d4;
}
@media (hover: hover) and (pointer: fine) { :root[data-theme='dark'] .btn.btn--danger:hover:not(:disabled) {
  background: #533543;
  border-color: #815367;
  color: #ffd0dd;
} }

/* Labels used for file uploads obey the same box model as button elements. */
.main .btn, .modal .btn {
  box-sizing: border-box;
  margin-block: 0;
  height: var(--action-height);
  min-height: var(--action-height);
  padding-block: 0;
  border-width: 1px;
  line-height: 1;
}
.nav__brand { justify-content: flex-start; direction: ltr; padding: 0 12px 20px; }
.nav__brand .brand-logo { width: 150px; height: 89px; object-fit: contain; border-radius: 0; background: none; }
.login-brand .brand-logo { width: 220px; height: 146px; object-fit: contain; border-radius: 0; background: none; }

:root[dir="rtl"] .nav__brand { justify-content: flex-end; }

/* Shared calendar surface for every office date field, including dialogs. */
.date-calendar { width: min(360px, calc(100vw - 32px)); padding: 20px; border: 1px solid var(--border); border-radius: 20px; color: var(--fg); background: var(--surface); box-shadow: 0 18px 60px #26354b22; }
.date-calendar::backdrop { background: #26354b33; }
.date-calendar__heading { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; font-size: 14px; }
.date-calendar__controls { display: grid; grid-template-columns: 30px 1fr 80px 30px; align-items: center; gap: 6px; padding: 10px 6px; border-radius: 12px; background: var(--tint-1); margin-bottom: 12px; direction: ltr; }
.date-calendar button { cursor: pointer; font-family: inherit; border: 1px solid transparent; color: var(--fg); }
.date-calendar__nav { width: 30px; height: 30px; padding: 0; border-radius: 50%; background: transparent; font-size: 20px; }
.date-calendar__controls select, .date-calendar__controls input { padding: 0 4px; width: 100%; height: 34px; min-width: 0; font-size: 12px; border: 0; border-radius: 8px; background-color: var(--surface); color: var(--fg); }
.date-calendar__days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.date-calendar__weekday { padding-block: 8px; text-align: center; font-size: 10px; color: var(--fg-muted); }
.date-calendar__day { height: 36px; padding: 0; border-radius: 10px; background: transparent; font-size: 12px; }
.date-calendar__day.is-today { border-color: #b8ace5; background: var(--tint-2); color: var(--tint-2-ink); }
.date-calendar__day[aria-pressed='true'] { background: var(--pill); color: var(--pill-ink); font-weight: 700; }
@media (hover: hover) and (pointer: fine) { .date-calendar button:hover:not(:disabled) { background: var(--tint-2); color: var(--tint-2-ink); } }
.date-calendar button:disabled { opacity: .35; cursor: default; }
.date-calendar :focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.date-calendar__foot { display: flex; gap: 10px; border-top: 1px solid var(--border); padding-top: 14px; margin-top: 14px; }
.date-calendar__foot button { flex: 1; height: 36px; border-radius: 8px; background: var(--surface-alt); font-size: 12px; }
.date-calendar__foot button:first-child { background: var(--pill); color: var(--pill-ink); }
input[type='date'] { border-radius: 10px; accent-color: var(--focus-ring); }
input[type='date']::-webkit-calendar-picker-indicator { opacity: .55; pointer-events: none; }
.calhead .icon-btn { background: var(--surface-alt); border: 1px solid var(--border); border-radius: 50%; box-shadow: none; }
button.weekday--now { background: var(--pill); color: var(--pill-ink); border-radius: 10px; }
@media (hover: hover) and (pointer: fine) { button.weekday--now:hover { background: var(--pill); color: var(--pill-ink); border-radius: 10px; } }
:root[data-theme='dark'] .date-calendar__controls { background: var(--tint-1); }
:root[data-theme='dark'] .date-calendar__day.is-today { background: var(--tint-2); color: var(--tint-2-ink); }
@media (hover: hover) and (pointer: fine) { :root[data-theme='dark'] .date-calendar button:hover:not(:disabled) { background: var(--tint-2); color: var(--tint-2-ink); } }

/* Date pickers open beside their field, above it when space below is tight. */
.date-calendar {
  position: fixed;
  inset: auto;
  margin: 0;
  z-index: 1000;
  max-height: calc(100dvh - 16px);
  overflow-y: auto;
}
.date-calendar::backdrop { background: transparent; }

/* Fees collection uses the same directory layout as Students and Staff. */
.finance-page .fin-table { padding: 0; border: 1px solid var(--border); border-radius: 18px; box-shadow: none; overflow: hidden; }
.finance-page .fin-table__head { margin: 0; padding: 20px 22px; gap: 18px; border-bottom: 1px solid var(--border); }
.finance-page .fin-table__head .card__title { font-size: 15px; font-weight: 600; }
.finance-page .fin-toolbar { width: 100%; gap: 10px; }
.finance-page .fin-search { flex: 1 1 220px; width: auto; height: 40px; border-radius: 10px; background: var(--surface); }
.finance-page .fin-search:focus-within { border-color: var(--focus-ring); box-shadow: 0 0 0 2px color-mix(in srgb, var(--focus-ring) 14%, transparent); }
.finance-page .fin-select { height: 40px; border-radius: 10px; flex: 1 1 135px; }
.finance-page .fin-select select { width: 100%; font-size: 12px; }
.finance-page .fin-tablewrap { border: 0; border-radius: 0; }
.finance-page .fin-grid { min-width: 940px; }
.finance-page .fin-grid thead th { height: 50px; padding: 0 14px; font-size: 12px; border-bottom: 1px solid var(--border); }
.finance-page .fin-grid thead th:first-child, .finance-page .fin-grid thead th:last-child { border-radius: 0; }
.finance-page .fin-grid tbody td { height: 68px; padding: 10px 14px; font-size: 12px; }
.finance-page .fin-grid tbody tr:last-child td { border-bottom: 0; }
.finance-page .fin-avatar { width: 33px; height: 33px; background: var(--tint-2); color: var(--tint-2-ink); }
.finance-page .fin-grid tbody tr:nth-child(3n+2) .fin-avatar { background: var(--tint-3); color: var(--tint-3-ink); }
.finance-page .fin-grid tbody tr:nth-child(3n) .fin-avatar { background: var(--tint-1); color: var(--tint-1-ink); }
.finance-page .fin-person__name { font-size: 12px; font-weight: 500; }
.finance-page .fin-person__meta { font-size: 10px; }
.finance-page .fin-check { width: 14px; height: 14px; border-width: 1px; border-color: #cfd3d8; }
.finance-page .fin-check:checked, .finance-page .fin-check:indeterminate { background: var(--focus-ring); border-color: var(--focus-ring); }
.finance-page .fin-chip { padding: 6px 10px; border-radius: 10px; font-size: 11px; font-weight: 500; }
.finance-page .fin-chip--paid { background: var(--tint-1); color: var(--tint-1-ink); }
.finance-page .fin-chip--pending { background: var(--tint-3); color: var(--tint-3-ink); }
.finance-page .fin-chip--overdue { background: #fff0f3; color: #a83c58; }
.finance-page .fin-chip--overdue .fin-chip__dot { background: #cc7990; }
.finance-page .fin-chip--pending .fin-chip__dot { background: #bea14d; }
.finance-page .fin-actions { gap: 8px; }
.finance-page .fin-actions .icon-btn { width: 32px; height: 32px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--fg-muted); box-shadow: none; }
.finance-page .fin-actions .icon-btn:first-child { background: var(--tint-1); border-color: #cfe8f3; color: var(--tint-1-ink); }
@media (hover: hover) and (pointer: fine) { .finance-page .fin-actions .icon-btn:hover { background: var(--tint-2); color: var(--tint-2-ink); } }
.finance-page .fin-pager { padding: 16px 22px; border-top: 1px solid var(--border); }
.finance-page .fin-pager .btn { min-width: 110px; height: 38px; }
.finance-page .fin-pager__info { font-size: 12px; }
:root[data-theme='dark'] .finance-page .fin-grid thead th { background: var(--tint-1); }
:root[data-theme='dark'] .finance-page .fin-avatar { background: var(--tint-2); color: var(--tint-2-ink); }
:root[data-theme='dark'] .finance-page .fin-grid tbody tr:nth-child(3n+2) .fin-avatar { background: var(--tint-3); color: var(--tint-3-ink); }
:root[data-theme='dark'] .finance-page .fin-grid tbody tr:nth-child(3n) .fin-avatar,
:root[data-theme='dark'] .finance-page .fin-chip--paid,
:root[data-theme='dark'] .finance-page .fin-actions .icon-btn:first-child { background: var(--tint-1); color: var(--pill); }
:root[data-theme='dark'] .finance-page .fin-chip--pending { background: var(--tint-3); color: var(--tint-3-ink); }
:root[data-theme='dark'] .finance-page .fin-chip--overdue { background: #3d1428; color: #ffb3d4; }
@media (max-width: 600px) {
  .finance-page .fin-table__head { padding: 18px; }
  .finance-page .fin-search { flex-basis: 100%; }
  .finance-page .fin-pager { padding: 14px; gap: 8px; }
  .finance-page .fin-pager .btn { min-width: 80px; }
}

.school-settings-logo { width: 140px; height: 100px; object-fit: contain; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-alt); padding: 8px; }

/* Nested navigation uses the same rounded controls without a second solid block. */
.nav .nav__sub {
  margin-block: 6px 9px;
  margin-inline-start: 20px;
  padding-inline-start: 10px;
  border-inline-start: 2px solid color-mix(in srgb, var(--school-secondary, #b9eaff) 55%, transparent);
  gap: 4px;
}
.nav .nav__sub a {
  min-height: 36px;
  margin: 0;
  padding: 8px 10px;
  border-radius: 8px;
  line-height: 1.4;
}
:root body .nav .nav__sub a[aria-current='page'] {
  background: color-mix(in srgb, var(--school-secondary, #b9eaff) 24%, transparent) !important;
  color: var(--fg) !important;
  font-weight: 600;
}
.nav .nav__sub a:focus-visible { outline: 2px solid var(--school-secondary, #b9eaff); outline-offset: 2px; }

/* Shared unsaved-changes confirmation, including RTL and small screens. */
dialog.discard-dialog { width: min(440px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); margin: auto; padding: 0; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); color: var(--fg); }
.discard-dialog .modal__head { padding: 24px 24px 0; border: 0; }
.discard-dialog .modal__body { padding: 16px 24px 24px; color: var(--fg-muted); line-height: 1.7; }
.discard-dialog .modal__body p { margin: 0; }
.discard-dialog .modal__foot { display: flex; padding: 16px 24px; gap: 12px; }
.discard-dialog .modal__foot .btn { flex: 1; min-width: 0; min-height: 42px; white-space: normal; }

.roll__row[data-status='sick_leave'] { border-color: var(--border); background: var(--primary-soft); }
.att--sick_leave { color: var(--fg); background: var(--primary-soft); }
.attendance-page .statuspicker button[data-s='sick_leave'][aria-pressed='true'] { background: var(--primary-soft); color: var(--fg); border-color: var(--border-strong); }
.attendance-page .statuspicker { flex-wrap: wrap; }
@media (pointer: coarse) { .attendance-page .statuspicker button { min-height: 44px; } }

/* The palette's sidebar rail is dark in both themes: always the light copy
   of the logo there. sidebar-light.css reverses this for its white rail. */
:root .nav .brand-logo.brand-logo--on-light { display: none; }
:root .nav .brand-logo.brand-logo--on-dark { display: block; }

/* ---------------------------------------- trial and subscription notices

   app.js standingBanner(). A strip between the app bar and the page, so it
   is on every screen without covering any of it. Amber when a date is
   coming; rose once the school is read-only, which is the state that
   changes what people can do. */
.standing {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 8px 26px 4px;
  padding: 13px 17px;
  border-radius: 14px;
  border: 1px solid transparent;
  font-size: 13px;
  line-height: 1.55;
}
.standing__body { flex: 1; min-width: 0; }
.standing__body strong { display: block; font-size: 14px; }
.standing__body p { margin: 2px 0 0; }
.standing__contact { font-weight: 600; }
.standing__hide { flex: none; }
.standing--warn { background: #fff1cc; border-color: #ffb703; color: #023047; }
.standing--readonly { background: #fde2ee; border-color: #f9a8cc; color: #a3124e; }
:root[data-theme='dark'] .standing--warn { background: #3a3320; border-color: #6b5a24; color: #ffd166; }
:root[data-theme='dark'] .standing--readonly { background: #3d1428; border-color: #6b1d40; color: #ffb3d4; }
@media (max-width: 900px) {
  .standing { margin-inline: 14px; flex-wrap: wrap; }
}

/* The free-trial label in the app bar - app.js trialChip(). Calm blue for
   most of the trial, the same amber as the warning banner in its last week. */
.trial-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid #8ecae6;
  border-radius: 999px;
  background: #e6f4fa;
  color: #023047;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .trial-chip:hover { background: #cfe8f3; } }
.trial-chip:focus-visible { outline: 2px solid var(--focus-ring, #00719c); outline-offset: 2px; }
.trial-chip__icon { display: inline-flex; width: 16px; height: 16px; }
.trial-chip__icon svg { width: 16px; height: 16px; }
.trial-chip--soon { border-color: #ffb703; background: #fff1cc; color: #023047; }
@media (hover: hover) and (pointer: fine) { .trial-chip--soon:hover { background: #ffefb8; } }
:root[data-theme='dark'] .trial-chip { border-color: #0b4560; background: #0b2533; color: #8ecae6; }
@media (hover: hover) and (pointer: fine) { :root[data-theme='dark'] .trial-chip:hover { background: #0a3d57; } }
:root[data-theme='dark'] .trial-chip--soon { border-color: #6b5a24; background: #3a3320; color: #ffd166; }
.trial-chip__short { display: none; }
.trial-info { display: grid; gap: 10px; padding-block: 4px 8px; line-height: 1.6; }
.trial-info p { margin: 0; }
.trial-info__lead { font-weight: 700; font-size: 15px; }
.trial-info__contact { font-weight: 600; }
/* On a phone the app bar has room for the clock and nothing else. */
@media (max-width: 560px) {
  .trial-chip { padding: 0 11px; }
  .trial-chip__text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .trial-chip__short { display: inline; }
}

/* The homeroom line on a class card opens the class editor for managers. */
.class-card__homeroom {
  padding: 2px 10px;
  border: 1px dashed transparent;
  border-radius: 8px;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .class-card__homeroom:hover { background: var(--surface-alt); border-color: var(--border-strong); } }
.class-card__homeroom--empty { border-color: var(--border-strong); color: var(--primary, var(--focus-ring)); font-weight: 600; }
.standing__deadline { font-weight: 700; }

/* ------------------------------------------------- weekly attendance chart

   dashboard.js bars(). One column per school day: a soft rounded track,
   and inside it a pill whose height is that day's register against the
   busiest day, split into who came (blue, from the bottom), excused or on
   sick leave (grey), and absent (pink, on top). The rate sits above; the
   full breakdown appears on hover or keyboard focus. Columns grow in when
   the dashboard opens, unless the visitor prefers reduced motion. */
.wk { display: grid; gap: 18px; }
.wk__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; }
.wk__avg strong { display: block; font-size: 30px; font-weight: 800; line-height: 1.05; letter-spacing: -0.02em; color: var(--fg); }
.wk__avg span { font-size: 12.5px; color: var(--fg-muted); }
.dashboard-home .wk .wk__legend { margin: 0; gap: 16px; }

.wk__plot { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; height: 250px; }
.wk__col {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  justify-items: center;
  gap: 8px;
  padding: 6px 0 4px;
  border-radius: 16px;
  outline: none;
  transition: opacity 0.2s ease, background-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) { .wk__plot:hover .wk__col:not(:hover) { opacity: 0.5; } }
.wk__col:focus-visible { background: var(--surface-alt); }
@media (hover: hover) and (pointer: fine) { .wk__col:hover { background: var(--surface-alt); } }
.wk__col:focus-visible { box-shadow: 0 0 0 2px var(--focus-ring); }

.wk__rate { font-size: 12px; font-weight: 700; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.wk__track {
  display: flex;
  align-items: flex-end;
  width: clamp(22px, 44%, 40px);
  height: 100%;
  border-radius: 999px;
  background: var(--surface-alt);
  overflow: hidden;
}
.wk__bar {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: calc(var(--h, 0) * 100%);
  border-radius: 999px;
  overflow: hidden;
}
.wk__seg--absent { flex: 0 0 calc(var(--a, 0) * 100%); background: var(--dash-absent); }
.wk__seg--other { flex: 1 1 auto; background: var(--border-strong); }
.wk__seg--present { flex: 0 0 calc(var(--p, 0) * 100%); background: var(--dash-present); }
.wk__day { font-size: 12.5px; font-weight: 600; color: var(--fg-subtle); }
.wk__col--today .wk__day { color: var(--fg); }
.wk__col--today .wk__day::after {
  content: '';
  display: block;
  width: 5px;
  height: 5px;
  margin: 4px auto 0;
  border-radius: 50%;
  background: var(--primary);
}
.wk__col--today .wk__track { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--dash-present) 40%, transparent); }

/* The breakdown opens beside the column it describes, never over it: the
   bar stays in view while its numbers are read, and the card's top edge
   cannot clip it. Columns in the last three open it on their other side. */
.wk__tip {
  position: absolute;
  top: 24px;
  inset-inline-start: calc(100% + 6px);
  z-index: 2;
  display: grid;
  gap: 4px;
  width: max-content;
  min-width: 150px;
  max-width: 240px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--fg);
  color: var(--surface);
  font-size: 12px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(4px);
  transition: opacity 0.15s cubic-bezier(0.23, 1, 0.32, 1), transform 0.15s cubic-bezier(0.23, 1, 0.32, 1);
}
.wk__col:nth-last-child(-n + 3) .wk__tip { inset-inline-start: auto; inset-inline-end: calc(100% + 6px); }
.wk__col:focus-visible .wk__tip { opacity: 1; transform: none; }
@media (hover: hover) and (pointer: fine) { .wk__col:hover .wk__tip { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .wk__tip { transform: none; transition: opacity 0.12s linear; }
  .wk__col { transition: none; }
}
.wk__tip-date { font-weight: 700; margin-block-end: 2px; }
.wk__tip-row { display: flex; justify-content: space-between; gap: 16px; opacity: 0.92; }
.wk__tip-row strong { font-variant-numeric: tabular-nums; white-space: nowrap; }

:root[data-theme='dark'] .wk__track { background: rgba(255, 255, 255, 0.05); }

@media (max-width: 560px) { .wk__plot { gap: 4px; height: 210px; } .wk__avg strong { font-size: 26px; } }

/* ------------------------------------------------------- students chart

   dashboard.js donut(). One ring - boys and girls as two rounded arcs with
   a gap between - the total in the middle, and a card for each half below
   with its share as a thin bar. The arcs draw in when the dashboard opens;
   hovering or focusing a card fades the other half of the ring. */
.sx { display: grid; justify-items: center; gap: 22px; }
.sx__donut { position: relative; width: min(230px, 100%); aspect-ratio: 1; }
.sx__ring { display: block; width: 100%; height: 100%; transform: rotate(-90deg); }
.sx__track, .sx__seg { fill: none; stroke-width: 14; }
.sx__track { stroke: var(--surface-alt); }
.sx__seg {
  stroke-linecap: round;
  stroke-dasharray: var(--len, 0) 100;
  transition: opacity 0.2s ease;
}
.sx__seg--boys { stroke: var(--dash-boys); }
.sx__seg--girls { stroke: var(--dash-girls); }

.sx__mid { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.sx__mid strong { font-size: 40px; font-weight: 800; line-height: 1; letter-spacing: -0.02em; color: var(--fg); }
.sx__mid span { margin-block-start: 6px; font-size: 13px; color: var(--fg-muted); }

.sx__cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; width: 100%; }
.sx__card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: 'icon pct' 'text text' 'bar bar';
  align-items: center;
  gap: 10px 12px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 16px;
  outline: none;
}
.sx__card:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* A plain colour mark for each half, the same colour as its arc. */
.sx__icon { grid-area: icon; width: 12px; height: 12px; border-radius: 3px; }
.sx__card--boys .sx__icon { background: var(--dash-boys); }
.sx__card--girls .sx__icon { background: var(--dash-girls); }
.sx__icon .dash-kid { display: none; }
.sx__text { grid-area: text; min-width: 0; }
.sx__count { font-size: 24px; font-weight: 800; line-height: 1.1; color: var(--fg); font-variant-numeric: tabular-nums; }
.sx__label { font-size: 13px; color: var(--fg-muted); }
.sx__pct { grid-area: pct; justify-self: end; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; color: var(--fg); background: var(--surface-alt); }
.sx__share { grid-area: bar; height: 6px; border-radius: 999px; background: var(--surface-alt); overflow: hidden; }
.sx__share-fill {
  display: block;
  height: 100%;
  width: calc(var(--w, 0) * 100%);
  border-radius: inherit;
}
.sx__card--boys .sx__share-fill { background: var(--dash-boys); }
.sx__card--girls .sx__share-fill { background: var(--dash-girls); }

/* Hovering a card fades the other half of the ring. */
.sx:has(.sx__card--boys:focus-visible) .sx__seg--girls, .sx:has(.sx__card--girls:focus-visible) .sx__seg--boys { opacity: 0.18; }
@media (hover: hover) and (pointer: fine) { .sx:has(.sx__card--boys:hover) .sx__seg--girls, .sx:has(.sx__card--girls:hover) .sx__seg--boys { opacity: 0.18; } }

@media (max-width: 420px) { .sx__cards { grid-template-columns: 1fr; } }

/* -------------------------------------------------------- dashboard tiles

   dashboard.js headTiles(). The four numbers that head the dashboard: flat
   palette colour, a plain line icon, the number, its name and one plain
   sentence of detail. No gradients, glows, frosted tiles, lifting or
   counting - the user wants the app to look made by people, not by AI. A
   tile you may open is a link; hovering darkens it a little. */
.dt-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
.dt {
  --dt-ink: #023047;
  display: flex;
  flex-direction: column;
  min-height: 168px;
  padding: 20px 22px;
  border-radius: 18px;
  color: var(--dt-ink);
  background: var(--dt-a);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
.dt--blue { --dt-a: var(--primary); }
.dt--sky { --dt-a: var(--pill); }
.dt--amber { --dt-a: var(--marigold); }
.dt--navy { --dt-a: #023047; --dt-ink: #ffffff; }
@media (hover: hover) and (pointer: fine) { a.dt:hover { background: color-mix(in srgb, var(--dt-a) 88%, #023047); text-decoration: none; } }
@media (hover: hover) and (pointer: fine) { .dt--navy:hover { background: #0b3d57; } }
a.dt:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }

.dt__icon { display: block; width: 24px; height: 24px; opacity: 0.85; }
.dt__icon svg { width: 24px; height: 24px; }
.dt__value { padding-block-start: 18px; font-size: 38px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.dt__label { margin-block-start: 6px; font-size: 14px; font-weight: 600; }
.dt__extra { display: grid; gap: 7px; margin-block-start: auto; padding-block-start: 12px; }
.dt__bar { display: flex; height: 5px; border-radius: 3px; background: rgb(255 255 255 / 0.4); overflow: hidden; }
.dt--navy .dt__bar { background: rgb(255 255 255 / 0.18); }
.dt__bar-seg { width: calc(var(--w, 0) * 100%); }
.dt__bar-seg--boys { background: #023047; }
.dt__bar-seg--girls { background: #f72585; }
.dt__bar-seg--came { background: #8ecae6; }
.dt__note { font-size: 12.5px; }
@media (max-width: 800px) {
  .dt-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .dt { min-height: 146px; padding: 16px 18px; }
  .dt__value { font-size: 30px; }
}

/* ---------------------------------------------------------- money columns

   charts.js columns(): the fees and expense charts and the dashboard's
   fees, drawn as the weekly attendance is - one column per month, the
   amount above it, the current month marked, the exact figure on hover or
   focus. Blue for money received, orange for money spent. Months still to
   come keep an empty track so the year's shape shows. */
.wk--in { --wk-tone: var(--dash-present); }
.wk--out { --wk-tone: var(--coral); }
.wk__seg--money { flex: 1 1 auto; background: var(--wk-tone); }
.wk--money .wk__plot { gap: 6px; }
.wk--money .wk__rate { font-size: 11px; white-space: nowrap; }
.wk--money .wk__day { font-size: 11.5px; white-space: nowrap; }
.wk__col--empty .wk__day { opacity: 0.55; }
@media (hover: hover) and (pointer: fine) { .wk__plot:hover .wk__col--empty { opacity: 1; } }
@media (max-width: 700px) {
  .wk--money .wk__plot { gap: 3px; }
  /* The amount above each column has no room on a phone. With it gone the
     column needs two rows, not three, or the bar drops into the empty
     first row and the chart draws nothing. */
  .wk--money .wk__rate { display: none; }
  .wk--money .wk__col { grid-template-rows: minmax(0, 1fr) auto; }
  /* Twelve month names do not fit side by side: every other one is shown,
     and always the current month, with its neighbours hidden when they
     would collide with it. The tooltip still names every month. */
  .wk--money .wk__col:nth-child(even) .wk__day,
  .wk--money .wk__col:has(+ .wk__col--today:nth-child(even)) .wk__day,
  .wk--money .wk__col--today:nth-child(even) + .wk__col .wk__day { visibility: hidden; }
  .wk--money .wk__col--today .wk__day { visibility: visible; }
  .wk--money .wk__day { font-size: 10px; }
  .wk--money .wk__track { width: clamp(10px, 60%, 22px); }
}

/* The small chart on the fee and expense cards: six thin columns, the
   latest one solid. */
.spark-wrap { display: inline-flex; flex-direction: column; gap: 4px; }
.spark.spark--cols {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  width: 64px;
  height: 26px;
  border-block-end: 1px solid color-mix(in srgb, currentColor 35%, transparent);
}
.spark--cols > span { flex: 1; height: calc(var(--h, 0) * 100%); border-radius: 2px 2px 0 0; background: currentColor; opacity: 0.35; }
.spark__caption { font-size: 10.5px; font-weight: 600; line-height: 1; opacity: 0.75; white-space: nowrap; }
.spark--cols > .spark__now { opacity: 1; }

/* Today's lessons for the office (dashboard.js schoolNow): the lessons being
   taught now and next, class by class. */
.tt-now-list { display: grid; gap: 16px; }
.tt-now__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-block-end: 8px; }
.tt-now__head strong { font-size: 14px; }
.tt-now__head span { font-size: 12.5px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.tt-now__rows { display: grid; gap: 6px; }
.tt-now__row {
  display: grid;
  grid-template-columns: minmax(5.5em, auto) minmax(0, 1fr);
  gap: 2px 12px;
  padding: 9px 12px;
  border-radius: 12px;
  background: var(--surface-alt);
}
.tt-now__class { grid-row: span 2; align-self: center; font-weight: 700; font-size: 13px; }
.tt-now__subject { font-weight: 600; font-size: 13.5px; }
.tt-now__teacher { font-size: 12px; color: var(--fg-muted); }
.check-inline { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.check-inline input { width: 18px; height: 18px; accent-color: var(--primary); }

/* ======================================================================
   The school calendar and the dated timetable (2026-10-05)

   One colour per kind of day, from the palette, used the same way
   everywhere it appears - the month grid, the timetable's day heads, the
   dashboard and the portal: pink for a holiday, grey for a closure, amber
   for exams, blue for an event or a cover. Flat fills only.
   ====================================================================== */
:root {
  --cal-holiday: var(--berry, #f72585);
  --cal-holiday-soft: var(--berry-soft, #fde2ee);
  --cal-holiday-ink: var(--berry-ink, #c2185b);
  --cal-closure: #8d99ae;
  --cal-closure-soft: color-mix(in srgb, #8d99ae 20%, var(--surface));
  --cal-closure-ink: var(--fg);
  --cal-exam: var(--marigold, #ffb703);
  --cal-exam-soft: var(--marigold-soft, #fff1cc);
  --cal-exam-ink: var(--marigold-ink, #023047);
  --cal-event: var(--primary);
  --cal-event-soft: var(--sky-soft, #e6f4fa);
  --cal-event-ink: var(--sky-ink, #023047);
}

.cal-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 3px; flex: none; vertical-align: middle; background: var(--cal-event); }
.cal-swatch--holiday { background: var(--cal-holiday); }
.cal-swatch--closure { background: var(--cal-closure); }
.cal-swatch--exam { background: var(--cal-exam); }

/* --- the month bar ---------------------------------------------------- */
.cal-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-block-end: var(--gap, 16px); }
.cal-bar__nav { display: flex; align-items: center; gap: 6px; }
.cal-bar__title { margin: 0; min-width: 9em; text-align: center; font-size: 18px; font-weight: 700; }
.cal-bar__step, .tt-weekbar__step { display: grid; place-items: center; padding-inline: 8px; }
.cal-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-inline-start: auto; font-size: 13px; color: var(--fg-muted); }
.cal-legend__item { display: inline-flex; align-items: center; gap: 6px; }

/* --- the month grid ---------------------------------------------------- */
.cal-card { overflow: hidden; }
.cal-grid__head, .cal-grid__days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-grid__dow {
  padding: 10px 6px;
  border-block-end: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: 12.5px;
  font-weight: 700;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cal-grid__dow--weekend { color: var(--fg-subtle); }
.cal-dow__short { display: none; }
.cal-day {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  min-height: 7.2rem;
  padding: 6px;
  border-inline-end: 1px solid var(--border);
  border-block-end: 1px solid var(--border);
}
.cal-grid__days > .cal-day:nth-child(7n) { border-inline-end: 0; }
.cal-day--weekend { background: var(--surface-alt); }
.cal-day--off.cal-day--holiday { background: var(--cal-holiday-soft); }
.cal-day--off.cal-day--closure { background: var(--cal-closure-soft); }
.cal-day__no {
  display: inline-grid;
  place-items: center;
  min-width: 28px;
  height: 28px;
  padding-inline: 4px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.cal-day--today .cal-day__no { background: var(--primary); color: var(--on-primary, #023047); }
.cal-day__add { align-self: flex-start; padding: 0; border: 0; border-radius: 999px; background: none; color: inherit; font: inherit; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .cal-day__add:hover .cal-day__no { background: var(--primary-soft); } }
@media (hover: hover) and (pointer: fine) { .cal-day--today .cal-day__add:hover .cal-day__no { background: var(--primary); } }
.cal-day__add:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.cal-day__events { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cal-ev {
  display: block;
  width: 100%;
  padding: 3px 7px;
  border: 0;
  border-inline-start: 3px solid var(--cal-event);
  border-radius: 6px;
  background: var(--cal-event-soft);
  color: var(--cal-event-ink);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  text-align: start;
}
.cal-ev__text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
button.cal-ev { cursor: pointer; }
@media (hover: hover) and (pointer: fine) { button.cal-ev:hover .cal-ev__text { text-decoration: underline; } }
button.cal-ev:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.cal-ev--holiday { border-color: var(--cal-holiday); background: var(--cal-holiday-soft); color: var(--cal-holiday-ink); }
.cal-ev--closure { border-color: var(--cal-closure); background: var(--cal-closure-soft); color: var(--cal-closure-ink); }
.cal-ev--exam { border-color: var(--cal-exam); background: var(--cal-exam-soft); color: var(--cal-exam-ink); }
/* On a shaded day the chip would vanish into its own colour. */
.cal-day--off .cal-ev { background: var(--surface); }
.cal-exams {
  align-self: flex-start;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--cal-exam-soft);
  color: var(--cal-exam-ink);
  font-size: 11.5px;
  font-weight: 700;
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { .cal-exams:hover { text-decoration: underline; } }

/* --- the month's list -------------------------------------------------- */
.cal-month-list { margin-block-start: var(--gap, 16px); }
.cal-list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.cal-list__item { display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px; border-radius: 12px; background: var(--surface-alt); }
.cal-list__item > .cal-swatch { margin-block-start: 7px; }
.cal-list__main { flex: 1; min-width: 0; }
.cal-list__title { font-weight: 700; }
.cal-list__meta { display: flex; flex-wrap: wrap; gap: 2px 12px; color: var(--fg-muted); font-size: 13px; }
.cal-list__note { margin-block-start: 2px; font-size: 13px; }
.cal-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 12px; }
.cal-dialog__hint[hidden] { display: none; }
.cal-dialog__danger { margin-block-start: 1rem; }

/* A phone shows the shape of the month - which days are off, which carry
   something - and the list under it says what. */
@media (max-width: 640px) {
  .cal-legend { margin-inline-start: 0; }
  .cal-grid__dow { padding: 8px 2px; font-size: 11px; }
  .cal-dow__full { display: none; }
  .cal-dow__short { display: inline; }
  .cal-day { min-height: 4.4rem; padding: 4px 3px; gap: 3px; }
  .cal-day__no { min-width: 24px; height: 24px; font-size: 13px; }
  .cal-ev { height: 6px; padding: 0; border: 0; border-radius: 3px; background: var(--cal-event); }
  .cal-ev--holiday { background: var(--cal-holiday); }
  .cal-ev--closure { background: var(--cal-closure); }
  .cal-ev--exam { background: var(--cal-exam); }
  .cal-day--off .cal-ev { background: var(--surface); }
  .cal-ev__text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .cal-exams { width: 8px; height: 8px; padding: 0; font-size: 0; background: var(--cal-exam); }
  .cal-two { grid-template-columns: minmax(0, 1fr); }
}

/* --- the timetable's week ---------------------------------------------- */
.tt-weekbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-block-end: 12px; }
.tt-weekbar__range { min-width: 11em; font-weight: 700; text-align: center; }
.tt-th__date { color: var(--fg-muted); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; }
.tt-th__note {
  margin-block-start: 4px;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--cal-event-soft);
  color: var(--cal-event-ink);
  font-size: 11.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tt-th__note--holiday { background: var(--cal-holiday-soft); color: var(--cal-holiday-ink); }
.tt-th__note--closure { background: var(--cal-closure-soft); color: var(--cal-closure-ink); }
.tt-th__note--exam { background: var(--cal-exam-soft); color: var(--cal-exam-ink); }
table.tt thead th.tt-th--today { box-shadow: inset 0 -3px 0 var(--primary); }
.tt-cell--off { min-height: 4.6rem; border-color: transparent; background: var(--surface-alt); opacity: 0.55; }
.tt-flag {
  display: inline-block;
  align-self: flex-start;
  max-width: 100%;
  margin-block-start: 3px;
  padding: 1px 7px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tt-flag--cover { background: var(--cal-event-soft); color: var(--cal-event-ink); }
.tt-flag--cancel { background: var(--cal-holiday-soft); color: var(--cal-holiday-ink); }
.tt-flag--exam { background: var(--cal-exam-soft); color: var(--cal-exam-ink); }
.tt-cell--cover, .tt-cell--covering { border-color: var(--cal-event); }
.tt-cell--covering { border-style: dashed; }
.tt-cell--exam { border-color: var(--cal-exam); }
.tt-cell--cancel .tt-cell__subject, .tt-cell--exam .tt-cell__subject { text-decoration: line-through; opacity: 0.7; }
.tt-exams {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 12px;
  margin-block-end: 12px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--cal-exam-soft);
  color: var(--cal-exam-ink);
  font-size: 13.5px;
}
.tt-exams__label { font-weight: 700; }
.tt-exams__list { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0; padding: 0; list-style: none; }
.tt-menu__who { margin: 0 0 8px; color: var(--fg-muted); }
.tt-menu__head { margin: 18px 0 8px; font-size: 14px; }
.tt-menu__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.tt-examday { margin-block-end: var(--gap, 16px); }
.tt-exam-single[hidden], .hint[hidden] { display: none; }

/* --- the dashboard ----------------------------------------------------- */
.tt-now__row .tt-flag { grid-column: 2; }
.agenda__row--cancel .agenda__what { text-decoration: line-through; opacity: 0.7; }
.dash-dayoff { padding: 16px; border-radius: 14px; background: var(--cal-holiday-soft); }
.dash-dayoff--closure { background: var(--cal-closure-soft); }
.dash-dayoff__title { font-size: 15px; font-weight: 700; }
.dash-dayoff__meta { margin-block-start: 4px; color: var(--fg-muted); font-size: 13px; }
.dash-exams-link { display: inline-block; margin-block-start: 12px; font-size: 13px; font-weight: 700; }
.dashboard-home button.weekday--off:not(.weekday--now) { background: var(--cal-holiday-soft); color: var(--cal-holiday-ink); }
.dash-list__title .cal-swatch { margin-inline-end: 2px; }
.att-dayoff { line-height: 1.6; }

@media print {
  .cal-bar__step, .cal-bar .btn, .tt-weekbar .btn { display: none; }
  .cal-day { min-height: 5.2rem; }
  .cal-ev { border: 0.75pt solid #999; }
}

/* ======================================================================
   Wide tables on a phone (2026-10-07)

   The expenses list and a student's fee history are desktop tables: on a
   phone the amount ended up off-screen or squeezed to "•••". Under 600px
   each row becomes a small stacked card - what it is and the amount on the
   first line, never cut; the date and reference under it; the category or
   the print button last. Amounts keep their width; text wraps instead.
   ====================================================================== */
@media (max-width: 600px) {
  :root body table.fin-grid--stack { min-width: 0; width: 100%; }
  :root body .fin-grid--stack thead,
  :root body table.ledger thead { display: none; }
  :root body .fin-grid--stack tbody,
  :root body table.ledger tbody { display: block; }
  :root body .fin-grid--stack tbody tr,
  :root body table.ledger tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 6px 14px;
    padding: 14px 4px;
    border-block-end: 1px solid var(--border);
  }
  :root body .fin-grid--stack tbody tr:last-child,
  :root body table.ledger tbody tr:last-child { border-block-end: 0; }
  :root body .fin-grid--stack tbody td,
  :root body table.ledger tbody td { display: block; height: auto; padding: 0; border: 0; min-width: 0; }

  /* expenses: date | payee | category | amount | recorded by | action */
  :root body .fin-grid--stack tbody tr { grid-template-areas: 'payee amount' 'date amount' 'cat action'; }
  :root body .fin-grid--stack tbody td:nth-child(1) { grid-area: date; }
  :root body .fin-grid--stack tbody td:nth-child(2) { grid-area: payee; }
  :root body .fin-grid--stack tbody td:nth-child(3) { grid-area: cat; }
  :root body .fin-grid--stack tbody td:nth-child(4) { grid-area: amount; text-align: end; white-space: nowrap; }
  :root body .fin-grid--stack tbody td:nth-child(5) { display: none; }
  :root body .fin-grid--stack tbody td:nth-child(6) { grid-area: action; justify-self: end; }
  :root body .fin-grid--stack tbody td:nth-child(1) .fin-person__text { display: flex; flex-wrap: wrap; gap: 0 10px; }
  :root body .fin-grid--stack tbody td:nth-child(1) .fin-person__name { font-weight: 400; color: var(--fg-muted); }
  :root body .fin-grid--stack tbody td:nth-child(2) .fin-person__name { font-weight: 600; white-space: normal; overflow-wrap: anywhere; }
  :root body .fin-grid--stack tbody td:nth-child(2) .fin-person__meta { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }

  /* fee history: date | what | receipt | amount | print */
  :root body table.ledger tbody tr { grid-template-areas: 'label amount' 'meta print'; grid-template-columns: minmax(0, 1fr) auto; }
  table.ledger .ledger__label { grid-area: label; font-weight: 600; overflow-wrap: anywhere; }
  table.ledger .ledger__amount { grid-area: amount; white-space: nowrap; text-align: end; }
  table.ledger .ledger__date,
  table.ledger .ledger__ref { grid-area: meta; color: var(--fg-muted); font-size: 13px; }
  table.ledger .ledger__ref { justify-self: end; }
  table.ledger .ledger__ref .subtle { display: none; }
  table.ledger .ledger__print { grid-area: print; justify-self: end; }
  table.ledger .ledger__print:empty { display: none; }
}

/* The weekly attendance chart counts who was missing (dashboard.js bars()):
   the bar grows from the bottom by the day's count, absent on the baseline
   with excused and sick leave above it, and a day nobody missed is an
   empty track. */
.wk--miss .wk__bar { flex-direction: column-reverse; }
.wk--miss .wk__seg--absent { flex: 0 0 calc(var(--a, 0) * 100%); }
.wk--miss .wk__seg--other { flex: 1 1 auto; }
.wk__caption { margin-block-start: -8px; font-size: 12.5px; color: var(--fg-muted); }

/* The inactivity warning (app.js): a quiet bar at the bottom of the screen
   with the countdown and "Stay signed in". A popover, so it shows above an
   open dialog. */
.idle-warning {
  position: fixed;
  inset: auto auto 20px 50%;
  transform: translateX(-50%);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: calc(100vw - 32px);
  padding: 12px 14px 12px 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  color: var(--fg);
  font-size: 14px;
  box-shadow: 0 18px 40px -14px rgb(16 24 40 / .35), 0 2px 6px rgb(16 24 40 / .08);
}
:root[dir='rtl'] .idle-warning { padding: 12px 18px 12px 14px; }
.idle-warning__text { flex: 1; min-width: 0; }
.idle-warning .btn { flex: none; }
@media (max-width: 560px) {
  .idle-warning { inset: auto 16px calc(16px + env(safe-area-inset-bottom, 0px)) 16px; transform: none; flex-wrap: wrap; }
}
