/* ==========================================================================
   IlmOS · base.css
   Tokens, reset, typography. This is the only file that defines colours -
   every other stylesheet works from these variables.
   ========================================================================== */

:root {
  color-scheme: light;

  /* --- surfaces: bright, cool, calm --------------------------------------- */
  --paper: #f5f6fb;
  --paper-2: #eceef6;
  --surface: #ffffff;
  --surface-1: #ffffff;
  --surface-2: #f8f9fc;

  /* --- ink --------------------------------------------------------------- */
  --ink: #13152b;
  --ink-2: #454a66;
  --ink-3: #5d627e;

  /* --- hairlines --------------------------------------------------------- */
  --rule: #e3e6f0;
  --rule-2: #cdd2e2;

  /* --- the school's colour -------------------------------------------------
     core/brand.ts writes --brand* on <html> from the school's own accent;
     these are the house defaults when a school has not picked one. */
  --pine: var(--brand, #4f46e5);
  --pine-2: var(--brand-2, #4338ca);
  --pine-ink: var(--brand-ink, #312e81);
  --pine-wash: var(--brand-wash, #eef0ff);
  /* Text that sits ON the school's colour. */
  --pine-fg: var(--brand-fg, #ffffff);

  /* --- school chrome (sidebar rail + name) ------------------------------- */
  --rail-bg: var(--brand-rail-bg, #ffffff);
  --rail-ink: var(--brand-rail-ink, #13152b);
  --rail-ink-2: var(--brand-rail-ink-2, #454a66);
  --rail-ink-3: var(--brand-rail-ink-3, #5d627e);
  --rail-rule: var(--brand-rail-rule, #e3e6f0);
  --rail-surface-2: var(--brand-rail-surface-2, #f8f9fc);
  --rail-wash: var(--brand-rail-wash, #eef0ff);
  --rail-active-ink: var(--brand-rail-active-ink, #312e81);
  --name-color: var(--brand-name, #13152b);

  /* --- second accent: records, reports and paper ------------------------- */
  --brass: #b45309;
  --brass-2: #92400e;
  --brass-wash: #fff4e0;

  /* --- signals ----------------------------------------------------------- */
  --ok: #047857;
  --ok-wash: #dcf7ea;
  --warn: #975a05;
  --warn-wash: #fff3d6;
  --bad: #c01c43;
  --bad-wash: #ffe8ee;
  --info: #1d4ed8;
  --info-wash: #e3edff;
  /* Text on a filled signal / brass background, and the tinted borders. */
  --on-signal: #ffffff;
  --ok-line: #a8dfc4;
  --warn-line: #f0d08e;
  --bad-line: #f4b3c3;
  --brass-line: #f1cf95;
  --brass-ink: #7a3a0a;
  --overlay: rgba(12, 14, 28, 0.5);
  --glass: rgba(255, 255, 255, 0.82);

  /* --- zone hues: every work area has its own, colour is never the only cue */
  --hue-entry: var(--pine);
  --hue-records: #0e7490;
  --hue-records-wash: #e0f5fa;
  --hue-reports: #b45309;
  --hue-setup: #475569;
  --hue-danger: #c01c43;

  /* --- geometry ---------------------------------------------------------- */
  --r-xs: 4px;
  --r-sm: 8px;
  --r: 12px;
  --r-lg: 16px;
  --r-xl: 22px;

  --lift-1: 0 1px 2px rgba(19, 21, 43, 0.05), 0 1px 1px rgba(19, 21, 43, 0.04);
  --lift-2: 0 2px 4px rgba(19, 21, 43, 0.04), 0 18px 40px -22px rgba(49, 46, 129, 0.35);
  --lift-3: 0 4px 10px rgba(19, 21, 43, 0.06), 0 30px 60px -28px rgba(49, 46, 129, 0.45);
  --glow: 0 10px 28px -12px color-mix(in srgb, var(--pine) 55%, transparent);
  /* The school's colour, lit from one corner: same hue, a touch brighter. */
  --grad-brand: linear-gradient(135deg, var(--pine) 0%, color-mix(in oklch, var(--pine) 82%, #ffffff) 100%);
  --page-tint: color-mix(in srgb, var(--pine) 7%, transparent);

  /* --- type -------------------------------------------------------------- */
  --font-sans: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Roboto, Arial, sans-serif;
  --font-display: "Segoe UI Variable Display", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Roboto, Arial, sans-serif;
  /* Kept as a name: headings used to be set in a serif. */
  --font-serif: var(--font-display);
  --font-mono: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;

  /* --- layout metrics ---------------------------------------------------- */
  --gut: 14px;
  --tap: 44px;
  --topbar-h: 56px;
  --tabs-h: 60px;
  --rail-w: 252px;
  --page-max: 1120px;
}

/* ==========================================================================
   Night theme. The inline script in <head> sets data-theme on <html> from
   the person's choice (light / night / follow the phone) before first paint.
   ========================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  --paper: #0c0e18;
  --paper-2: #121524;
  --surface: #161a2b;
  --surface-1: #161a2b;
  --surface-2: #1c2135;

  --ink: #eef0fb;
  --ink-2: #bcc1dc;
  --ink-3: #9aa0c0;

  --rule: #272c44;
  --rule-2: #363c5a;

  --pine: var(--brand-n, #8b93ff);
  --pine-2: var(--brand-n2, #a5acff);
  --pine-ink: var(--brand-n-ink, #dfe2ff);
  --pine-wash: var(--brand-n-wash, #25294f);
  --pine-fg: var(--brand-n-fg, #0c0e18);

  --rail-bg: #11141f;
  --rail-ink: #eef0fb;
  --rail-ink-2: #bcc1dc;
  --rail-ink-3: #9aa0c0;
  --rail-rule: #232842;
  --rail-surface-2: #181c2d;
  --rail-wash: var(--brand-n-wash, #25294f);
  --rail-active-ink: var(--brand-n-ink, #dfe2ff);
  --name-color: var(--brand-n, #8b93ff);

  --brass: #f5a524;
  --brass-2: #fbbf24;
  --brass-wash: #2e2410;

  --ok: #34d399;
  --ok-wash: #0f2e25;
  --warn: #fbbf24;
  --warn-wash: #2e2410;
  --bad: #fb7185;
  --bad-wash: #3a1520;
  --info: #93c5fd;
  --info-wash: #152544;
  --on-signal: #0c0e18;
  --ok-line: #1d5a47;
  --warn-line: #5b4712;
  --bad-line: #6b2437;
  --brass-line: #5b4712;
  --brass-ink: #fcd34d;
  --overlay: rgba(0, 0, 0, 0.62);
  --glass: rgba(22, 26, 43, 0.82);

  --hue-records: #22d3ee;
  --hue-records-wash: #0d2a33;
  --hue-reports: #f5a524;
  --hue-setup: #94a3b8;
  --hue-danger: #fb7185;

  --lift-1: 0 1px 2px rgba(0, 0, 0, 0.5);
  --lift-2: 0 2px 4px rgba(0, 0, 0, 0.35), 0 18px 40px -22px rgba(0, 0, 0, 0.8);
  --lift-3: 0 4px 10px rgba(0, 0, 0, 0.4), 0 30px 60px -28px rgba(0, 0, 0, 0.9);
  --glow: 0 10px 30px -12px color-mix(in srgb, var(--pine) 60%, transparent);
  --page-tint: color-mix(in srgb, var(--pine) 10%, transparent);
}

/* A printed or paper-styled sheet is always light, whatever the theme. */
.paper {
  color-scheme: light;
  --paper: #f5f6fb;
  --surface: #ffffff;
  --surface-2: #f8f9fc;
  --ink: #13152b;
  --ink-2: #454a66;
  --ink-3: #5d627e;
  --rule: #e3e6f0;
  --rule-2: #cdd2e2;
  --pine: var(--brand, #4f46e5);
  --pine-2: var(--brand-2, #4338ca);
  --pine-ink: var(--brand-ink, #312e81);
  --pine-wash: var(--brand-wash, #eef0ff);
  --pine-fg: var(--brand-fg, #ffffff);
  --brass: #b45309;
  --brass-2: #92400e;
  --brass-wash: #fff4e0;
  --ok: #047857;
  --ok-wash: #dcf7ea;
  --warn: #975a05;
  --warn-wash: #fff3d6;
  --bad: #c01c43;
  --bad-wash: #ffe8ee;
}

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

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

body {
  margin: 0;
  padding: 0;
  background-color: var(--paper);
  background-image:
    radial-gradient(1100px 420px at 0% -8%, var(--page-tint), transparent 70%),
    radial-gradient(800px 380px at 105% -10%, color-mix(in srgb, #ec4899 6%, transparent), transparent 70%);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.16;
  color: var(--ink);
}

p {
  margin: 0;
}

a {
  color: var(--pine);
  text-decoration: none;
}

a:hover {
  color: var(--pine-2);
}

img {
  max-width: 100%;
  display: block;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--pine);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

::selection {
  background: var(--pine-wash);
  color: var(--pine-ink);
}

.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  letter-spacing: -0.01em;
}

.muted {
  color: var(--ink-3);
}

.strong {
  font-weight: 600;
}

.nowrap {
  white-space: nowrap;
}

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

/* Table cell alignment helpers (used by the table component) --------------- */
.t-right {
  text-align: right;
}

.t-center {
  text-align: center;
}

.t-left {
  text-align: left;
}

/* A figure that is a problem: outstanding money, a failed mark ------------ */
.t-bad {
  color: var(--bad);
  font-weight: 650;
}

/* Small screens: columns the phone can live without ----------------------- */
@media (max-width: 719px) {
  .col-phone-hidden {
    display: none;
  }
}

/* ==========================================================================
   Compact & overflow rules — the screen adapts to any width, nothing ever
   pushes the page wider. Applied globally so every module benefits.
   ========================================================================== */

/* Long words, IDs, URLs and long student names break instead of overflowing */
.table td,
.table th,
.meta__row dd,
.card__body,
.callout,
.field__hint,
.field__error,
.toast {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Keep values readable but contained */
.meta__row dd {
  min-width: 0;
}

/* Numbers and references never stretch a column */
.table .code,
dd .code,
.code {
  overflow-wrap: anywhere;
}

/* Images and media can never exceed their container */
img,
svg,
video,
iframe {
  max-width: 100%;
}

/* Grid children must be allowed to shrink below their content width */
.grid-2 > *,
.stat-grid > *,
.hub-grid > *,
.form-grid > *,
.check-grid > *,
.stat,
.card,
.big-action,
.field {
  min-width: 0;
}

/* Small phones (<360px): tighten padding and type so nothing clips */
@media (max-width: 359px) {
  :root {
    --gut: 10px;
  }

  body {
    font-size: 14px;
  }

  .card__body,
  .card__head {
    padding-left: 10px;
    padding-right: 10px;
  }

  .table th,
  .table td {
    padding-left: 8px;
    padding-right: 8px;
    font-size: 13px;
  }

  .stat__value {
    font-size: 21px;
  }
}

/* Very compact landscape phones / narrow splits */
@media (max-height: 420px) and (orientation: landscape) {
  .topbar {
    position: static;
  }

  .main {
    padding-bottom: 24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Cross-document view transitions: a soft crossfade on navigation, desktop
   only. Inside Android's WebView (the portal app) the transition can hang on
   the first navigation — the login POST — and leave a white page behind, so
   phones and the app always navigate plainly. */
@media (min-width: 1024px) and (hover: hover) {
  @view-transition {
    navigation: auto;
  }
}

/* ==========================================================================
   Streaming skeletons + soft page-in
   Shell paints first; streamed content lands where the skeleton sat (same
   footprint → no layout jump). Animations are transform/opacity only.
   ========================================================================== */
@keyframes skel-shimmer {
  0% {
    opacity: 0.55;
  }

  50% {
    opacity: 1;
  }

  100% {
    opacity: 0.55;
  }
}

@keyframes soft-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.stream-fallback {
  display: grid;
  gap: 16px;
}

.skel {
  background: linear-gradient(
    90deg,
    var(--surface-2, #eef2f1) 25%,
    var(--surface-1, #f7f9f8) 37%,
    var(--surface-2, #eef2f1) 63%
  );
  background-size: 400% 100%;
  border-radius: 10px;
  animation: skel-shimmer 1.4s ease-in-out infinite;
}

.skel--title {
  height: 28px;
  width: min(280px, 60%);
}

.skel--tile {
  height: 88px;
}

.skel--block {
  height: 48px;
}

.skel--panel {
  height: 160px;
}

.main > * {
  animation: soft-in 180ms ease-out;
}

/* ==========================================================================
   Zone accent
   The page states which zone it belongs to (body.zone--*), so the chrome can
   pick one accent colour instead of every component guessing its own.
   ========================================================================== */
body.zone--home {
  --zone-accent: var(--pine);
}

body.zone--entry {
  --zone-accent: var(--pine);
}

body.zone--records {
  --zone-accent: var(--hue-records);
}

body.zone--reports {
  --zone-accent: var(--hue-reports);
}

body.zone--setup {
  --zone-accent: var(--hue-setup);
}

body.zone--danger {
  --zone-accent: var(--hue-danger);
}
