/*
 * PalliOS — "Greenfield" design system (Chalkboard & Marigold).
 * Ported verbatim from the Node reference app (apps/web/src/app/globals.css) so the CI4 front-end
 * matches the same brand tokens, shell chrome, and component classes. This file is the single source
 * of truth for the CI4 web UI — screens link it and use these classes instead of per-file inline CSS.
 */
:root {
  --graphite: #26322d;      /* primary — dark rail/header, nav, primary buttons */
  --rail: #212b26;          /* deepest ink — header/rail background */
  --marigold: #e7a63c;      /* accent — active states, the "OS" wordmark, CTAs */
  --marigold-deep: #dc9526; /* marigold hover/pressed */
  --marigold-text: #8a5f16; /* marigold as small text / on-cream chips (AA) */
  --chalk: #fbf8f1;         /* page canvas (warm cream) */
  --surface: #ffffff;       /* cards / raised surfaces */
  --line: #eae4d4;          /* hairline borders on cards */
  --line-2: #e7e1d0;        /* stronger border — header, search, inputs */
  --sand: #f6ebd6;          /* soft accent fill — chips, icon wells */
  --slate: #6b7370;         /* secondary text */
  --kumkum: #9a3b3b;        /* destructive / error / absent / overdue */
  --forest: #2a8f5b;        /* positive / up / present */

  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-body: 'Public Sans', 'Noto Sans Tamil', system-ui, sans-serif;
  --font-tamil: 'Noto Sans Tamil', 'Public Sans', system-ui, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--chalk);
  color: var(--graphite);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
:lang(ta) { font-family: var(--font-tamil); }

/* ── Tamil optical sizing ───────────────────────────────────────────────────
   Noto Sans Tamil sets a noticeably larger apparent size than Public Sans at the same px — Tamil
   glyphs are taller and carry more internal detail — so a bilingual line reads as if the Tamil is
   shouting. This scales it back to match the Latin optically.

   The two rules are deliberately mutually exclusive, because the naive `:lang(ta) { font-size }`
   COMPOUNDS: `<html lang="ta">` already puts every element in :lang(ta), so an inline
   `<span lang="ta">` inside it would be scaled twice, and a third time if ever nested again.
     • A Tamil PAGE scales once at the root, which carries the whole screen and the navigation with
       it, since the shell's type is in rem.
     • A Tamil FRAGMENT on an English page scales itself — and only on English pages, which is what
       the :not() prevents from stacking on top of the root scale above.

   px-based touch targets (min-height 44px) are unaffected, so this cannot shrink a tap target below
   the NFR-11 floor. */
:root { --ta-scale: 0.92; }
html[lang="ta"] { font-size: calc(100% * var(--ta-scale)); }
html[lang="ta"] body { font-size: calc(16px * var(--ta-scale)); }
html:not([lang="ta"]) [lang="ta"] { font-size: calc(1em * var(--ta-scale)); }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--graphite);
}
a { color: inherit; text-decoration: none; }

/* ── Header ─────────────────────────────────────────────────────────────── */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1.25rem;
  background: var(--rail);
  color: var(--chalk);
  border-bottom: 3px solid var(--marigold);
  /* Fixed, not sticky: the app sets `overflow-x: hidden` on <body>, which turns the body into a
     scroll container and quietly cancels position:sticky (the header scrolled away). Fixed is immune —
     it pins to the viewport so only the content below scrolls. `left/right:0` span the full width so
     the logo starts at the left edge with no cream gap (the top-left "white box"). */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
}
/* App pages offset their content below the fixed header. Scoped to the app shell so the sign-in and
   public pages (which have no .app-header) are untouched. Mobile's header wraps to two rows, so it
   needs a taller offset (see the ≤820px block). */
body.app-shell { padding-top: var(--header-h); }
.brand-lockup { display: inline-flex; align-items: center; gap: 0.5rem; color: inherit; }
/* The horizontal lockup carries the wordmark inside the asset, so there is no text to style — only
   a height to hold. Width is set on the element from the 422.22:1000 intrinsic ratio; `height:auto`
   here would let a narrow flex parent squash it, so the height is pinned and the width follows. */
.brandlogo { display: block; height: 36px; width: auto; flex: none; }
.app-header-school {
  font-size: 0.55rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase;
  color: rgba(251, 248, 241, 0.7); border-left: 1px solid rgba(251, 248, 241, 0.3); padding-left: 0.6rem;
}
.app-header .spacer { flex: 1; }
.app-header .who { text-align: right; font-size: 0.8rem; line-height: 1.25; }
.app-header .who b { display: block; font-weight: 700; }
.app-header .who span { color: rgba(251, 248, 241, 0.7); font-size: 0.72rem; }
/* Role glyph + label sit on one baseline, right-aligned with the name above them. */
.app-header .who-role { display: inline-flex; align-items: center; gap: 0.3rem; justify-content: flex-end; }
.roleicon { flex: none; }

/* ── Layout ─────────────────────────────────────────────────────────────── */
/* Full-width content (was boxed to 1080px): fill the available width beside the rail, edge padding only. */
.container { max-width: none; margin: 0; padding: 1.5rem 1.5rem 3rem; }
.container.wide { max-width: 1180px; }
/* Page title matches the Next.js frontend, where pages render a plain serif <h1> at the UA-default
   2em (32px) with the global Newsreader/500/-0.01em treatment — CI4 had shrunk it to 1.7rem. */
.page-title { margin: 0 0 0.25rem; font-size: 2rem; }
.page-title .accent { color: var(--marigold); }
.sub { color: var(--slate); margin: 0 0 1.25rem; font-size: 0.95rem; }
.muted { color: var(--slate); }
.num { font-variant-numeric: tabular-nums; }
.stack { display: flex; flex-direction: column; gap: 1rem; }
.hstack { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.vstack { display: flex; flex-direction: column; gap: 0.5rem; }

/* Back navigation shown on every sub-screen (design consistency). */
.back-nav { margin: 0 0 0.85rem; }
.back-link { font-size: 0.85rem; color: var(--slate); font-weight: 600; display: inline-flex; align-items: center; gap: 0.2rem; }
.back-link:hover { color: var(--marigold-text); }

/* Pagination for management lists (reusable, responsive — wraps on narrow screens). */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-top: 1rem; font-size: 0.85rem; }
.pager-info { color: var(--slate); }
.pager-links { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.btn.disabled, .btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
.toolbar { display: flex; align-items: end; gap: 0.85rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
.toolbar .grow { flex: 1; min-width: 180px; }

/* ── Cards ──────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.25rem;
  box-shadow: 0 1px 2px rgba(38, 50, 45, 0.04);
}
.card + .card { margin-top: 1rem; }
.card h3 { margin: 0 0 0.85rem; font-size: 1.05rem; }
.card-title { font-family: var(--font-display); font-size: 1.05rem; margin: 0 0 0.85rem; }

/* ── Nav tiles (dashboard) ──────────────────────────────────────────────── */
.nav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.85rem; margin-top: 1.25rem; }
.nav-tile {
  display: block; padding: 1rem; background: var(--surface); border: 1px solid var(--line);
  border-left: 4px solid var(--marigold); border-radius: 10px; font-weight: 600;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
a.nav-tile:hover { border-color: var(--marigold); box-shadow: 0 4px 12px rgba(38, 50, 45, 0.07); transform: translateY(-1px); }
/* Icon well — the tile now carries the same stroke glyph as the shell nav, in a sand well. */
.nav-tile .ic {
  display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px;
  border-radius: 10px; background: var(--sand); color: var(--marigold-text); margin-bottom: 0.55rem;
}
.nav-tile .ic svg { width: 20px; height: 20px; }
.nav-tile b { display: block; margin: 0.5rem 0 0.15rem; font-size: 0.98rem; }
.nav-tile p { margin: 0; color: var(--slate); font-size: 0.8rem; font-weight: 400; line-height: 1.4; }
.nav-tile .pg { float: right; font-size: 0.62rem; letter-spacing: 0.04em; color: var(--forest); background: #eaf5ee; border: 1px solid #cde7d6; padding: 2px 7px; border-radius: 20px; }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.6rem 1rem; border-radius: 9px; border: 1px solid transparent; font: inherit;
  font-weight: 700; cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease; text-decoration: none;
}
.btn-primary { background: var(--graphite); color: var(--chalk); }
.btn-primary:hover { background: var(--rail); }
.btn-accent { background: var(--marigold); color: var(--graphite); font-weight: 800; }
.btn-accent:hover { background: var(--marigold-deep); }
.btn-ghost { background: transparent; border-color: var(--line-2); color: var(--graphite); }
.btn-ghost:hover { border-color: var(--marigold); }
.btn-danger { background: #fbeaea; color: var(--kumkum); border-color: #f0c9c9; }
.btn-danger:hover { border-color: var(--kumkum); }
.btn-sm { padding: 0.4rem 0.7rem; font-size: 0.82rem; border-radius: 7px; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; flex: none;
  padding: 0; border-radius: 999px; border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  background: transparent; color: inherit; cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease;
}
.icon-btn:hover { border-color: var(--marigold); background: color-mix(in srgb, currentColor 8%, transparent); }
/* The language switch is an icon now, so it needs no type rules — only the marigold hint that marks
   it out from the neighbouring icon buttons, and a centred glyph. */
.lang-toggle { display: inline-flex; align-items: center; justify-content: center; border-color: color-mix(in srgb, var(--marigold) 60%, transparent); }
.lang-toggle svg { display: block; }
.icon-action {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface); color: var(--slate); cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.icon-action + .icon-action { margin-inline-start: 5px; }
.icon-action:hover { border-color: var(--marigold); color: var(--graphite); background: color-mix(in srgb, var(--marigold) 8%, transparent); }
.icon-action.danger:hover { border-color: var(--kumkum); color: var(--kumkum); background: color-mix(in srgb, var(--kumkum) 8%, transparent); }

/* A table cell of row actions. Each POST action needs its own <form>, so the buttons are not
   adjacent siblings and `.icon-action + .icon-action` cannot space them — the flex gap does. */
.row-actions { display: flex; gap: 5px; align-items: center; justify-content: flex-end; white-space: nowrap; }
.row-actions form { display: inline; margin: 0; }

/* ── Forms ──────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.9rem; }
.field label { font-size: 0.8rem; color: var(--slate); font-weight: 600; }
.field input, .field select, .field textarea {
  padding: 0.6rem 0.7rem; border: 1px solid var(--line-2); border-radius: 9px; font: inherit;
  background: var(--surface); transition: border-color 0.15s ease; width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--marigold); box-shadow: 0 0 0 3px rgba(231, 166, 60, 0.16); }
.field textarea { min-height: 72px; resize: vertical; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0 1rem; }
.form-grid .field { margin-bottom: 0.75rem; }
/* A boolean field is a checkbox beside its own label, so it opts out of the stacked .field layout. */
.chk { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--slate); font-weight: 600; margin-bottom: 0.75rem; align-self: end; }
.chk input { width: auto; }
.req { color: var(--kumkum); }

.tabs { display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
.tab { padding: 0.5rem 0.9rem; border: 1px solid var(--line); background: var(--sand); border-radius: 9px; font: inherit; font-weight: 700; cursor: pointer; color: var(--slate); text-decoration: none; }
.tab.on, .tab[aria-selected='true'] { background: var(--surface); color: var(--graphite); border-color: var(--marigold); }

/* ── Banners ────────────────────────────────────────────────────────────── */
.flash { background: #eaf5ee; color: #256e45; border: 1px solid #bfe3cd; padding: 0.7rem 0.9rem; border-radius: 9px; margin-bottom: 1rem; font-weight: 600; }
.err { background: #fbeaea; color: var(--kumkum); border: 1px solid #f0c9c9; padding: 0.7rem 0.9rem; border-radius: 9px; margin-bottom: 1rem; }
.note { background: var(--sand); color: var(--marigold-text); border: 1px solid var(--line-2); padding: 0.7rem 0.9rem; border-radius: 9px; margin-bottom: 1rem; }
.empty { color: #98a0a8; padding: 1.15rem; text-align: center; }

/* ── Auth ───────────────────────────────────────────────────────────────── */
.auth-wrap { min-height: 100dvh; display: grid; place-items: center; padding: 1.5rem; background: linear-gradient(135deg, var(--chalk) 0%, var(--sand) 100%); }
/* The stacked lockup at 90px is only 102px wide, so the card needs no extra room for it. */
.auth-card { width: 100%; max-width: 380px; }

/* Sign-in card head. The stacked lockup is centred in the flow while the language switch is pulled
   out of it and pinned to the corner, so the logo stays optically centred in the card rather than
   being nudged left by a sibling sharing its row. */
.auth-head { position: relative; text-align: center; margin-bottom: 1.4rem; }
/* The lockup's intrinsic size is set for a desktop card; this lets it shrink rather than overflow.
   Without it a 500px-wide mark would run off the side of any phone. */
.auth-head .brandlogo { margin: 0 auto; max-width: 100%; height: auto; }
.auth-lang { position: absolute; right: 0; top: 0; }
.auth-tagline { margin: 0.7rem 0 0; font-size: 0.85rem; }
/* Room for the pinned switch, so a long tagline cannot run under it. */
.auth-head .auth-tagline { padding-inline: 2.5rem; }

.auth-foot { margin: 1.4rem 0 0; text-align: center; font-size: 0.8rem; }
.auth-foot a { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--slate); min-height: 44px; }
.auth-foot a:hover { color: var(--graphite); }

/* ── Tables ─────────────────────────────────────────────────────────────── */
table.data { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.data thead th {
  text-align: start; font-size: 0.75rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--marigold-text); padding: 0.6rem 0.9rem; background: var(--sand);
}
table.data tbody td { padding: 0.6rem 0.9rem; border-top: 1px solid var(--line); vertical-align: top; }
table.data tbody tr:hover { background: rgba(231, 166, 60, 0.06); }
table.data td.r, table.data th.r { text-align: end; }
table.data td.c, table.data th.c { text-align: center; }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ── Badges / pills ─────────────────────────────────────────────────────── */
.badge { display: inline-block; padding: 0.12rem 0.55rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700; }
.badge-current, .badge-graphite { background: var(--graphite); color: var(--chalk); }
.badge-hs, .badge-accent { background: var(--marigold); color: var(--graphite); }
.pill { display: inline-block; padding: 0.12rem 0.55rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700; }
.pill.ok, .pill.present, .pill.approved, .pill.paid { background: #eaf5ee; color: var(--forest); }
.pill.bad, .pill.absent, .pill.rejected, .pill.overdue { background: #fbeaea; color: var(--kumkum); }
.pill.warn, .pill.draft, .pill.pending, .pill.partial { background: var(--sand); color: var(--marigold-text); }

/* ── Key-value grid (profiles) ──────────────────────────────────────────── */
dl.kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.85rem 1.25rem; margin: 0; }
dl.kv dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--slate); font-weight: 700; }
dl.kv dd { margin: 0.15rem 0 0; font-size: 0.95rem; }

/* ── Stat cards ─────────────────────────────────────────────────────────── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 0.85rem; }
/* Stat card = the same KPI card the dashboard uses; aligned to the Next.js DashboardShell values
   (0.64rem/800 label, 1.7rem/500 serif value, 12×14 padding) so every page's stats read identically. */
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 0.75rem 0.9rem; }
.stat .k { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--slate); font-weight: 800; }
.stat .v { font-family: var(--font-display); font-size: 1.7rem; font-weight: 500; line-height: 1; margin-top: 0.35rem; }
.stat .v.up { color: var(--forest); } .stat .v.down { color: var(--kumkum); }

footer.app-footer { text-align: center; color: #98a0a8; font-size: 0.78rem; padding: 1.5rem; }

/* ── Responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  .app-header { padding: 0.55rem 0.85rem; gap: 0.5rem; }
  /* The fixed header wraps to two rows here (search on its own line, ~102px), so the content clears
     that taller bar rather than the single-row --header-h. */
  body.app-shell { padding-top: 108px; }
  .app-header-school { display: none; }
  .app-header .brandlogo { height: 30px; }
  .app-header .who span { display: none; }
  .container { padding: 1.1rem 0.85rem 3rem; }
}
/* Below 380px the lockup's wordmark would crowd the search field; drop to the mark's own width. */
@media (max-width: 380px) { .app-header .brandlogo { height: 26px; } }

/* ═══════════════════════════════════════════════════════════════════════════
 * Shell navigation — design-03 §2.2/§5
 * 58 px dark icon rail on desktop; the same items as a fixed bottom tab bar at
 * ≤820 px. The fifth slot is a `<details>` flyout listing every remaining module
 * the role can open, which is what keeps a five-item rail from hiding the other
 * twenty screens ("never more than two taps from any screen it can access").
 * ═══════════════════════════════════════════════════════════════════════════ */
:root { --header-h: 61px; --rail-w: 58px; }

.app-nav {
  position: fixed; z-index: 40; background: var(--rail); color: var(--chalk);
  display: flex; overflow: visible;
}
.nav-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: rgba(251, 248, 241, 0.72); text-decoration: none; cursor: pointer;
  font-size: 0.58rem; font-weight: 700; letter-spacing: 0.02em; text-align: center;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item svg { width: 21px; height: 21px; flex: none; }
.nav-item span { line-height: 1.15; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item:hover { color: var(--chalk); background: rgba(251, 248, 241, 0.08); }
/* Active state is never colour alone (NFR-11): the marigold fill is paired with a solid edge marker. */
.nav-item.on { color: var(--marigold); background: rgba(251, 248, 241, 0.14); }
.nav-item.on::after { content: ''; position: absolute; background: var(--marigold); }

/* Flyout — a native details/summary, so it works with no JS and is keyboard-operable. */
.nav-more { position: relative; }
.nav-more > summary {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  width: 100%; height: 100%; list-style: none; cursor: pointer;
}
.nav-more > summary::-webkit-details-marker { display: none; }
.nav-more[open] > summary { color: var(--marigold); background: rgba(251, 248, 241, 0.14); }
.nav-flyout {
  /* .nav-item centres its own label; the flyout is nested inside it and must not inherit that. */
  text-align: start;
  position: fixed; z-index: 60; background: var(--surface); color: var(--graphite);
  border: 1px solid var(--line-2); border-radius: 12px; box-shadow: 0 12px 32px rgba(33, 43, 38, 0.22);
  padding: 0.5rem; width: min(310px, calc(100vw - 1.5rem)); max-height: min(70vh, 520px); overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.nav-flyout-title {
  margin: 0.2rem 0.5rem 0.45rem; font-size: 0.62rem; font-weight: 800; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--slate);
}
.nav-flyout a {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.55rem; border-radius: 9px;
  color: var(--graphite); text-decoration: none;
}
.nav-flyout a:hover { background: var(--sand); }
.nav-flyout a[aria-current='page'] { background: var(--sand); box-shadow: inset 3px 0 0 var(--marigold); }
.nav-flyout-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex: none;
  border-radius: 8px; background: var(--sand); color: var(--marigold-text);
}
.nav-flyout-icon svg { width: 17px; height: 17px; }
.nav-flyout a b { display: block; font-size: 0.86rem; font-weight: 700; }
.nav-flyout a em { display: block; font-style: normal; font-size: 0.72rem; color: var(--slate); line-height: 1.3; }

/* ── Desktop: vertical rail ─────────────────────────────────────────────── */
@media (min-width: 821px) {
  .app-nav { top: var(--header-h); left: 0; bottom: 0; width: var(--rail-w); flex-direction: column; padding-top: 0.4rem; }
  .nav-item { position: relative; width: 100%; min-height: 52px; padding: 0.4rem 0.15rem; }
  .nav-item.on::after { inset-inline-start: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; }
  .nav-more > summary { min-height: 52px; padding: 0.4rem 0.15rem; }
  /* 58 px is an ICON rail (design-03 §5). A label squeezed into it truncates, and in Tamil the stub
     is ambiguous — "செயல் பலகை" (Dashboard) and "செயல் பதிவு" (Audit Log) both became "செயல் ப…".
     The name lives on aria-label/title instead, so it is announced and shown on hover, never clipped. */
  .app-nav .nav-item > span, .app-nav .nav-more > summary > span { display: none; }
  .app-nav .nav-item svg { width: 22px; height: 22px; }
  .nav-flyout {
    inset-inline-start: calc(var(--rail-w) + 8px); bottom: 12px;
    max-height: calc(100vh - var(--header-h) - 24px);
  }
  body { padding-inline-start: var(--rail-w); }
}

/* ── Mobile ≤820 px: bottom tab bar ─────────────────────────────────────── */
@media (max-width: 820px) {
  .app-nav {
    left: 0; right: 0; bottom: 0; flex-direction: row;
    border-top: 1px solid rgba(251, 248, 241, 0.14);
    /* Clear the iOS home indicator — without this the last row of tabs sits under it. */
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .nav-item { position: relative; flex: 1 1 0; min-width: 0; min-height: 52px; padding: 0.35rem 0.1rem; }
  .nav-item.on::after { top: 0; inset-inline-start: 20%; inset-inline-end: 20%; height: 3px; border-radius: 0 0 3px 3px; }
  .nav-more { flex: 1 1 0; min-width: 0; }
  .nav-more > summary { min-height: 52px; padding: 0.35rem 0.1rem; }
  .nav-flyout {
    bottom: calc(52px + env(safe-area-inset-bottom, 0px) + 8px); inset-inline-end: 8px;
    max-height: calc(100vh - 52px - var(--header-h) - 24px);
  }
  /* Leave room for the bar itself plus the home indicator. */
  .container { padding-bottom: calc(52px + 1.5rem + env(safe-area-inset-bottom, 0)); }
  footer.app-footer { padding-bottom: calc(52px + 1rem + env(safe-area-inset-bottom, 0)); }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Touch targets — NFR-11 (≥44 px, attendance ≥48 px)
 * Scoped to coarse pointers so the desktop office screens keep their density:
 * the spec is desktop-first for office, mobile-first for parents and teachers.
 * ═══════════════════════════════════════════════════════════════════════════ */
@media (pointer: coarse) {
  .btn, .tab, .icon-btn, .icon-action,
  .field input, .field select, .field textarea { min-height: 44px; }
  .btn-sm { min-height: 44px; padding-block: 0.5rem; }
  .icon-btn, .icon-action { min-width: 44px; }
  .att-btn, .attendance-actions .btn { min-height: 48px; }
  /* A tap on a table row's action should not need aim. */
  table.data td .btn-sm { padding-inline: 0.9rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Accessibility + cross-platform hardening (NFR-11, NFR-12)
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Keyboard operability: a visible focus ring everywhere, never removed. */
:focus-visible {
  outline: 3px solid var(--marigold);
  outline-offset: 2px;
  border-radius: 4px;
}
.app-nav :focus-visible { outline-color: var(--chalk); outline-offset: -3px; }

/* Skip link — the first tab stop, so keyboard users bypass the rail on every page. */
.skip-link {
  position: absolute; inset-inline-start: -9999px; top: 0; z-index: 100;
  background: var(--marigold); color: var(--graphite); font-weight: 800;
  padding: 0.7rem 1.1rem; border-radius: 0 0 10px 0;
}
.skip-link:focus { inset-inline-start: 0; }

/* Narrow phones (NFR-12 floor is 360 px): tab strips scroll instead of stacking
   into a wall, and tables keep their own scroller rather than widening the page. */
@media (max-width: 480px) {
  .tabs {
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; padding-bottom: 2px;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex: none; }
  .stat-grid { grid-template-columns: 1fr 1fr; gap: 0.6rem; }
  .container { padding-inline: 0.7rem; }
}
@media (max-width: 360px) {
  .stat-grid { grid-template-columns: 1fr; }
}

/* The page itself must never scroll sideways — only designated containers do. */
html, body { max-width: 100%; overflow-x: hidden; }
.table-scroll, table.data { max-width: 100%; }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Money and marks line up only with tabular figures (design-03 §5). */
table.data td.r, table.data th.r, .stat .v, .num { font-variant-numeric: tabular-nums; }

/* Respect a user's reduced-motion setting (NFR-11). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
  a.nav-tile:hover { transform: none; }
}

/* Print: drop the chrome so registers and receipts print as documents. */
@media print {
  .app-nav, .app-header, .skip-link, footer.app-footer, .btn, .tabs { display: none !important; }
  body { padding: 0 !important; background: #fff; }
  .container { max-width: none; padding: 0; }
  .card { border: 1px solid #ccc; box-shadow: none; break-inside: avoid; }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Role home / dashboard — ported from the Node DashboardShell (design-03 §5).
 * KPIs are the hero row; quick-links are the compact secondary row; the bottom
 * pair is a 7fr/5fr chart + trending split that stacks on narrow screens.
 * ═══════════════════════════════════════════════════════════════════════════ */
.dash-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 0.9rem;
}
.dash-greet { font-family: var(--font-display); font-size: 1.45rem; font-weight: 500; margin: 0; }
.dash-greet .accent { color: var(--marigold-text); }
.dash-date { font-size: 0.78rem; color: var(--slate); margin: 0.2rem 0 0; }

/* KPI cards — uppercase slate label / Newsreader value / tone-coloured delta. */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.75rem; margin-bottom: 0.8rem; }
.kpi { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 0.75rem 0.9rem; }
.kpi-k { font-size: 0.64rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; color: var(--slate); }
.kpi-v {
  font-family: var(--font-display); font-size: 1.7rem; font-weight: 500; line-height: 1;
  margin-top: 0.35rem; font-variant-numeric: tabular-nums;
}
.kpi-d { font-size: 0.7rem; font-weight: 600; margin-top: 0.25rem; min-height: 1em; color: var(--slate); }
.kpi-d.up { color: var(--forest); }
.kpi-d.down { color: var(--kumkum); }

/* Quick-links — compact, one line each. The big tile grid was the whole page before; here it is
   the secondary row, so the numbers above it can be the answer to "how are we doing today?". */
.quick-links { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; margin-bottom: 0.8rem; }
.quick-link {
  display: flex; align-items: center; gap: 0.5rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: 10px; padding: 0.5rem 0.6rem;
  font-size: 0.78rem; font-weight: 700; color: var(--graphite); text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.quick-link:hover { border-color: var(--marigold); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(38, 50, 45, 0.07); }
.ql-ic {
  display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  flex: none; border-radius: 7px; background: var(--sand); color: var(--marigold-text);
}
.ql-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Chart + trending */
.dash-split { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 0.75rem; }
.panel-h { font-size: 0.85rem; font-weight: 800; font-family: var(--font-body); margin: 0; display: flex; align-items: center; gap: 0.45rem; }
.panel-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.4rem; }
.pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--marigold); flex: none; animation: pallios-pulse 2s infinite; }
@keyframes pallios-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.bars { display: flex; align-items: flex-end; gap: 0.75rem; margin-top: 1rem; min-height: 120px; }
.bar-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 0.25rem; }
.bar-v { font-size: 0.64rem; font-weight: 700; color: #a39b87; font-variant-numeric: tabular-nums; }
.bar-v.hi { color: var(--graphite); }
.bar { width: 100%; max-width: 36px; min-height: 4px; border-radius: 5px 5px 0 0; background: #eae3cf; }
.bar.hi { background: var(--marigold); }
.bar-l {
  font-size: 0.6rem; color: #98917f; font-weight: 700; letter-spacing: 0.02em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.trend-item { padding: 0.6rem 0 0.55rem; border-top: 1px solid #f0eada; }
.trend-item:first-of-type { border-top: 0; }
.trend-t { font-size: 0.8rem; font-weight: 700; margin-top: 0.3rem; }
.chip {
  display: inline-block; font-size: 0.62rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase;
  background: var(--sand); color: var(--marigold-text); padding: 2px 7px; border-radius: 5px;
}

/* Content for assistive tech that must not be painted (the chart's data table). */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

@media (max-width: 820px) {
  /* Stack the pair — a 5fr column is unreadable on a phone. */
  .dash-split { grid-template-columns: 1fr; }
  .dash-greet { font-size: 1.25rem; }
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.6rem; }
  .dash-head .btn { width: 100%; justify-content: center; }
}
@media (max-width: 480px) {
  .kpi-row { grid-template-columns: 1fr 1fr; }
  .quick-links { grid-template-columns: 1fr 1fr; }
  .bars { gap: 0.4rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Header search, avatar, nav badge, search results, reports hub
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Global search in the top bar (design-03 §5). A form, not an overlay. */
.hdr-search { position: relative; display: flex; align-items: center; flex: 1 1 220px; max-width: 340px; min-width: 0; }
.hdr-search svg { position: absolute; inset-inline-start: 10px; color: rgba(251, 248, 241, 0.55); pointer-events: none; }
.hdr-search input {
  width: 100%; font: inherit; font-size: 0.78rem; color: var(--chalk);
  background: rgba(251, 248, 241, 0.1); border: 1px solid transparent; border-radius: 9px;
  padding: 0.45rem 0.6rem 0.45rem 2rem;
}
.hdr-search input::placeholder { color: rgba(251, 248, 241, 0.5); }
.hdr-search input:focus { outline: none; border-color: var(--marigold); background: rgba(251, 248, 241, 0.16); }
/* Safari renders a proprietary clear button that sits badly on the dark bar. */
.hdr-search input::-webkit-search-decoration,
.hdr-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.avatar {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex: none;
  border-radius: 999px; background: var(--marigold); color: var(--graphite);
  font-size: 0.7rem; font-weight: 800; letter-spacing: 0.02em;
}

/* Unread badge on the Inbox nav item. */
.nav-badge {
  position: absolute; top: 6px; inset-inline-end: 12px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; background: var(--marigold); color: var(--graphite);
  font-size: 0.55rem; font-weight: 800; line-height: 15px; text-align: center;
}

/* Search results */
.result-list { list-style: none; margin: 0.4rem 0 0; padding: 0; }
.result-list li + li { border-top: 1px solid var(--line); }
.result-list a { display: block; padding: 0.6rem 0.2rem; border-radius: 8px; color: var(--graphite); text-decoration: none; }
.result-list a:hover { background: var(--sand); }
.result-list b { display: block; font-size: 0.9rem; }
.result-list em { display: block; font-style: normal; font-size: 0.75rem; color: var(--slate); margin-top: 1px; }

/* Reports hub */
.report-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.6rem; }
.report-item {
  display: flex; align-items: center; gap: 0.6rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: 10px; padding: 0.7rem 0.85rem;
  color: var(--graphite); text-decoration: none; transition: border-color 0.15s ease, transform 0.15s ease;
}
.report-item:hover { border-color: var(--marigold); transform: translateY(-1px); }
.ri-body { flex: 1; min-width: 0; }
.report-item b { display: block; font-size: 0.82rem; font-weight: 700; }
.report-item em { display: block; font-style: normal; font-size: 0.7rem; color: var(--slate); margin-top: 1px; }
.ri-go { flex: none; color: var(--marigold-text); }

@media (max-width: 820px) {
  /* The bar is tight on a phone; search moves to its own row under the brand. */
  .app-header { flex-wrap: wrap; row-gap: 0.5rem; }
  .hdr-search { order: 3; flex-basis: 100%; max-width: none; }
  .avatar { display: none; }
}

/* Brand mark svg — was inline style="flex:none" (blocked by strict style-src). */
.brandmark { flex: none; }
