/* Archivo, self-hosted.
 *
 * It was loaded by @import from Google Fonts and it never actually arrived: an @import
 * inside a stylesheet is fetched only after that stylesheet parses, and the woff2 from
 * fonts.gstatic.com was blocked outright — five of the six faces stayed `unloaded` and
 * the product rendered in Helvetica while reporting "Archivo" as its computed family.
 *
 * Self-hosting removes the third-party round trip and the failure mode with it. The
 * variable file carries both axes: weight 400–700 and width 62–125, which the width
 * convention in this design depends on. font-display: swap so text is never invisible.
 */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('/public/fonts/archivo-latin.woff2') format('woff2-variations'),
       url('/public/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
                 U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('/public/fonts/archivo-latin-ext.woff2') format('woff2-variations'),
       url('/public/fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================================
   Schoo — design tokens

   THE SINGLE PLACE COLOUR IS DEFINED. Every other stylesheet, and every view,
   reads from here. Nothing below this file should contain a hex value: if you
   find yourself typing one, the token you need is missing and belongs here.

   Structure
     1. Palette          the fourteen colours the product is allowed to use
     2. Roles            what components actually reference
     3. Shape & motion   radii, the one shadow, spacing, timing
     4. Type             one family, one scale, one width axis
     5. Bootstrap bridge overrides so the framework inherits all of the above
   ========================================================================= */

:root {
  /* -- 1. Palette ----------------------------------------------------------
     Fourteen colours. Blue carries the brand AND the "present" state, so a
     fully-attended register is entirely blue and an exception is the only
     thing on the screen wearing another colour. Amber and red are for genuine
     exceptions only — a late mark, an absence, an overdue fee, a register not
     yet taken. Nothing outside this list appears anywhere in the product. */
  --navy-900:  #0E1A3C;   /* top bar, primary text, primary button fill */
  --navy-700:  #2F3F68;   /* secondary text */
  /* Specified as #6B7A9B. Darkened by 1.6% lightness — a 4/255 channel shift, visually
     the same colour — because #6B7A9B is 4.30:1 on white and this product holds itself
     to 4.5:1 for text. It is used for every meta line and muted label, so the gap
     applied to most of the small text in the app. Revert to #6B7A9B if the brand spec
     must win over the contrast floor; the two cannot both hold here. */
  --slate-500: #667697;   /* muted text, meta lines */
  --slate-300: #A8B3CC;   /* placeholders, disabled */
  --blue-600:  #2A46E0;   /* primary accent, links, "present" */
  --blue-100:  #E4E9FD;   /* soft blue fill */
  --canvas:    #EDF1F9;   /* app background, avatar discs */
  --line:      #DCE3F0;   /* card and field borders */
  --line-soft: #E9EEF8;   /* list row dividers */
  --white:     #FFFFFF;   /* surfaces */
  --amber-600: #B0761C;   /* late, warnings */
  --amber-100: #FBEEDA;
  --red-600:   #B4392C;   /* absent, overdue, alerts */
  --red-100:   #F8E4E0;

  /* -- 2. Roles ------------------------------------------------------------
     Components reference these, never the palette directly, so a re-skin is
     section 1 and nothing else.

     Attendance is this product's vocabulary, so present/late/absent are named
     for what they are and the generic status roles alias onto them. Each state
     has a fill (legible as a solid shape), a tint (a chip or band ground) and
     a text stop dark enough to sit on its own tint — those three are not
     interchangeable. */
  --present:        var(--blue-600);
  --present-tint:   var(--blue-100);
  /* Words on the blue tint, 8.67:1. --blue-600 would pass at 5.69 but reads as a link
     rather than a state when set as a sentence. */
  --present-text:   #1B2FA6;

  --late:           var(--amber-600);
  --late-tint:      var(--amber-100);
  /* Words on the amber tint, 5.91:1. --amber-600 itself is only 3.36:1 there, so a
     warning sentence needs this darker stop; --amber-600 stays the fill and the dot. */
  --late-text:      #7E5210;

  --absent:         var(--red-600);
  --absent-tint:    var(--red-100);
  --absent-text:    var(--red-600);   /* 4.82:1 on its own tint — passes as-is */

  --ok:            var(--present);
  --ok-surface:    var(--present-tint);
  --ok-border:     var(--blue-100);
  --ok-fill:       var(--present);

  --warn:          var(--late);
  --warn-surface:  var(--late-tint);
  --warn-border:   var(--amber-100);
  --warn-fill:     var(--late);

  --danger:        var(--absent);
  --danger-surface:var(--absent-tint);
  --danger-border: var(--red-100);
  --danger-fill:   var(--absent);

  /* No separate info colour. A fifth hue would be one more than the palette
     allows, and "informational" is what plain text on canvas already says. */
  --info:          var(--navy-700);
  --info-surface:  var(--canvas);
  --info-border:   var(--line);

  --bg:              var(--canvas);
  --surface:         var(--white);
  --surface-sunken:  var(--canvas);
  --surface-raised:  var(--white);
  --surface-inverse: var(--navy-900);

  --border:          var(--line);
  --border-soft:     var(--line-soft);
  --border-strong:   var(--slate-300);

  --text:            var(--navy-900);
  --text-secondary:  var(--navy-700);
  --text-muted:      var(--slate-500);
  --text-subtle:     var(--slate-300);   /* placeholders and disabled only */
  --text-inverse:    var(--white);
  --text-on-brand:   var(--white);

  --accent:          var(--blue-600);
  --accent-hover:    var(--navy-900);
  --accent-subtle:   var(--blue-100);
  --accent-border:   var(--blue-100);

  --focus-ring:      0 0 0 3px rgba(42, 70, 224, 0.35);

  /* Aliases kept so the ramp names still resolve for anything not yet moved
     onto the roles above. */
  --brand-50:  var(--blue-100);
  --brand-100: var(--blue-100);
  --brand-200: var(--blue-100);
  --brand-300: var(--slate-300);
  --brand-400: var(--slate-500);
  --brand-500: var(--blue-600);
  --brand-600: var(--blue-600);
  --brand-700: var(--navy-900);
  --brand-800: var(--navy-900);
  --brand-900: var(--navy-900);
  --n-0:   var(--white);
  --n-25:  var(--white);
  --n-50:  var(--canvas);
  --n-100: var(--canvas);
  --n-200: var(--line);
  --n-300: var(--slate-300);
  --n-400: var(--slate-300);
  --n-500: var(--slate-500);
  --n-600: var(--navy-700);
  --n-700: var(--navy-700);
  --n-800: var(--navy-900);
  --n-850: var(--navy-900);
  --n-900: var(--navy-900);

  --sidebar-bg:        var(--navy-900);
  --sidebar-text:      var(--slate-300);
  --sidebar-text-hover:var(--white);
  --sidebar-active-bg: rgba(255, 255, 255, 0.10);
  --sidebar-active-bar:var(--blue-600);
  --sidebar-section:   var(--slate-500);

  /* -- 5. Shape, depth, spacing, motion -----------------------------------
     Modularity is mostly consistency: one radius scale, one shadow scale, one
     spacing step. Components that pick their own stop looking like a set. */
  /* Radius varies by role. One radius for everything is how a card, a field and a
     state pill stop being different kinds of thing. */
  --r-xs: 4px;
  --r-sm: 7px;
  --r-md: 10px;    /* inputs and buttons */
  --r-lg: 16px;    /* cards */
  --r-xl: 22px;
  --r-full: 999px; /* state pills, the search field, discs */

  /* Exactly one shadow in the product, on the fixed bottom action bar — the only
     element that genuinely floats above the page. Everything else separates with a
     hairline. The rest of the scale resolves to none so a stray reference cannot
     quietly reintroduce a second elevation. */
  --shadow-bar: 0 -2px 12px rgba(14, 26, 60, 0.10);
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: var(--shadow-bar);
  --shadow-brand: none;

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;

  /* The height a field or a button standing on a filter row is floored to, so the
     two always line up. Derived from .form-control's own padding and line height. */
  --control-h: 42px;
  --sp-4: 18px;   /* the standard gutter */
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;

  /* -- 6. Type -------------------------------------------------------------
     Archivo, a grotesque with a real width axis. The width is the point: this
     product is mostly names, batches and money in narrow columns, and being
     able to condense a heading rather than shrink it keeps a long batch name
     on one line at full size.

     The convention is optical — the larger the type, the narrower it is set,
     so a 31px date and a 13px label look like the same typeface rather than
     one being a blown-up version of the other. */
  --font: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --stretch-display: 92%;
  --stretch-heading: 96%;
  --stretch-title:   98%;
  --stretch-normal:  100%;
  --stretch-wide:    112%;   /* the mark, and uppercase micro-labels */

  /* One type scale. Sizes outside it are how a product stops looking like a set. */
  /* 11.5 / 12.5 / 13.5 / 15.5 / 20 / 27 / 31, at a 16px root. */
  --t-xs:   0.719rem;   /* 11.5 */
  --t-sm:   0.781rem;   /* 12.5 */
  --t-md:   0.844rem;   /* 13.5 */
  --t-base: 0.969rem;   /* 15.5 */
  --t-lg:   1.250rem;   /* 20   */
  --t-xl:   1.688rem;   /* 27   */
  --t-2xl:  1.938rem;   /* 31   */
  --t-3xl:  1.938rem;   /* 31 — the scale stops here */

  /* Display figures — money, percentages, tallies — are the thing people
     actually read. Set tight, tabular and condensed so columns align and a
     total carries weight without shouting. */
  --figure-weight: 700;
  --tally-size: 1.438rem;   /* 23px — the register tally, its own step */
  --figure-tracking: -0.022em;
  --figure-stretch: var(--stretch-display);

  /* Motion has its own namespace. It used to live on --t-*, which collided with
     the type scale: --t-base was declared as a size and then again as a duration,
     so every `font-size: var(--t-base)` in the product resolved to a duration and
     was silently dropped — card titles and empty-state headings among them. */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --motion-fast: 120ms var(--ease);
  --motion-base: 200ms var(--ease);

  /* Kept so existing rules keep working. Prefer --motion-fast. */
  --t-fast: var(--motion-fast);

  /* -- 7. Bootstrap bridge -------------------------------------------------
     Bootstrap 5 is loaded from a CDN and cannot be recompiled, so its own
     variables are pointed at the tokens above. Without this every .btn-primary,
     .badge and .form-control keeps Bootstrap's default blue and the page ends
     up wearing two palettes at once. */
  --bs-primary:        var(--brand-600);
  --bs-primary-rgb:    42, 70, 224;
  --bs-secondary:      var(--n-500);
  --bs-secondary-rgb:  107, 122, 155;
  --bs-success:        var(--ok);
  --bs-success-rgb:    42, 70, 224;
  --bs-warning:        var(--warn);
  --bs-warning-rgb:    176, 118, 28;
  --bs-danger:         var(--danger);
  --bs-danger-rgb:     180, 57, 44;
  --bs-info:           var(--info);
  --bs-info-rgb:       47, 63, 104;
  --bs-body-bg:        var(--bg);
  --bs-body-color:     var(--text);
  --bs-border-color:   var(--border);
  --bs-border-radius:  var(--r-md);
  --bs-body-font-family: var(--font);
  --bs-link-color:     var(--accent);
  --bs-link-hover-color: var(--accent-hover);

  /* Names the previous stylesheet used. Kept as aliases so nothing breaks
     mid-migration; delete once no rule references them. */
  --primary-color:       var(--brand-900);
  --primary-hover-color: var(--brand-800);
  --secondary-color:     var(--brand-600);
  --secondary-hover-color: var(--brand-700);
  --background-light:    var(--bg);
  --text-dark:           var(--text);
  --text-light:          var(--text-inverse);
  --sidebar-hover-bg:    var(--sidebar-active-bg);
}

/* Archivo's width axis is the identity. Without this the browser fakes it by
   scaling glyphs, which looks like a stretched font rather than a designed one. */
html { font-synthesis-weight: none; }

/* ---------------------------------------------------------------------------
   Print. Ink is expensive and a dark bar on paper is nobody's friend.
   ------------------------------------------------------------------------ */
@media print {
  :root {
    --bg: #FFFFFF;
    --surface: #FFFFFF;
    --surface-sunken: #FFFFFF;
    --text: #000000;
    --text-muted: #444444;
    --border: #999999;
    --shadow-xs: none; --shadow-sm: none; --shadow-md: none; --shadow-lg: none;
  }
}
