/* ==========================================================================
   base.css — Design tokens, reset, typography, and layout primitives
   VIS Student Council 2026–27
   --------------------------------------------------------------------------
   This file defines the single source of truth for colours, spacing, type,
   and borders via CSS custom properties. Change a value here and it updates
   everywhere. Component styling lives in components.css; admin-only styling
   lives in admin.css.
   ========================================================================== */

/* ---- Design tokens ------------------------------------------------------- */
:root {
  /* Brand — the deep maroon sampled directly from the STUCO badge (#901830).
     Dark enough to pass WCAG AA as text on white (8.9:1), so one colour works
     for fills, links, and accents alike. */
  --brand:        #901830;
  --brand-text:   #901830;
  --brand-dark:   #6e1225;
  --brand-tint:   #f7e9ec;

  /* Neutral foundation — warm, rose-tinted greys that sit naturally next to
     the maroon badge (cool blue-greys would fight it). */
  --gray-50:  #faf6f7;
  --gray-100: #f3edee;
  --gray-200: #e7dde0;
  --gray-300: #d1c3c7;
  --gray-400: #9f8e93;
  --gray-500: #6f6165;
  --gray-600: #514549;
  --gray-700: #3a3134;
  --gray-800: #272124;
  --gray-900: #1d1519;

  /* Semantic — status colours. Always paired with text/icon, never colour alone. */
  --success:      #1f7a44;
  --success-tint: #e6f2ea;
  --warning:      #9a6700;
  --warning-tint: #fbf1d9;
  --danger:       #b01d23;
  --danger-tint:  #fbecec;
  --info:         #1c5d9c;
  --info-tint:    #e7f0f9;

  /* Surfaces */
  --bg:        #ffffff;
  --bg-muted:  var(--gray-50);
  --text:      var(--gray-900);
  --text-soft: var(--gray-600);
  --border:    var(--gray-200);
  --border-strong: var(--gray-300);

  /* Typography — two working families plus the logo face, each with an
     explicit Traditional Chinese companion so bilingual content never falls
     back to unrelated system fonts:
     - DM Sans (+ Noto Sans TC): ALL interface text — headings, nav,
       buttons, forms, tables, filters, badges, metrics — ALL text.
     - Chewy: ONLY inside the official nav logo lockup, never for content
       and never for Chinese text. */
  --font-sans: "DM Sans", "Noto Sans TC", "PingFang TC",
               "Microsoft JhengHei", "Segoe UI", Arial, sans-serif;
  --font-display: var(--font-sans);
  --font-brand: "Chewy", "Noto Sans TC", sans-serif;
  --font-mono: "SFMono-Regular", ui-monospace, Menlo, Consolas, monospace;

  --fs-xs:   0.8125rem;  /* 13px — metadata, labels */
  --fs-sm:   0.9375rem;  /* 15px — tables, secondary UI */
  --fs-base: 1.0625rem;  /* 17px — body */
  --fs-md:   1.25rem;    /* 20px — small headings */
  --fs-lg:   1.5rem;     /* 24px — h3, item headlines */
  --fs-xl:   clamp(2rem, 3.4vw, 2.875rem);    /* section titles 32–46px */
  --fs-2xl:  clamp(2.5rem, 4.5vw, 4rem);      /* major titles 40–64px */
  --fs-3xl:  3.25rem;    /* page-heading ceiling */
  /* Display sizes for editorial composition */
  --fs-hero:    clamp(2.75rem, 6.5vw, 5.25rem);  /* hero statement 44–84px */
  --fs-numeral: clamp(4.5rem, 10vw, 8rem);       /* structural numerals 72–128px */

  /* Reference-style leading: headings nearly solid, prose comfortable */
  --lh-tight: 1.02;
  --lh-snug:  1.3;
  --lh-base:  1.5;

  /* Spacing — 4px base scale */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* Borders & radius — reference language: pill controls, and cards with a
     signature asymmetric corner (one tucked corner, three round). */
  --radius-sm: 8px;
  --radius:    14px;
  --radius-card: 24px 24px 24px 6px;
  --border-w:  1px;

  /* One subtle shadow, used sparingly (not on every card) */
  --shadow-sm: 0 1px 2px rgba(20, 23, 27, 0.06);
  --shadow-pop: 0 4px 16px rgba(20, 23, 27, 0.10);

  /* Focus — high-contrast, GOV.UK-style: black text keyline over a yellow band
     so focus is unmistakable on any background. */
  --focus-ring:   #ffbf00;
  --focus-inset:  #14171b;

  /* Layout — wide editorial container, narrow reading column */
  --container: 1120px;
  --container-wide: 1360px;
  --container-narrow: 720px;
  --space-9: 6rem;   /* large editorial section spacing (96px) */
  /* Fixed header height so the full-screen hero can size itself to exactly
     one viewport: header + hero = 100svh (see .hero in components.css). */
  --header-h: 5rem;

  /* Motion — only for state changes; disabled under reduced-motion below */
  --transition: 150ms ease;
}

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

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

body {
  margin: 0;
  /* One family everywhere: DM Sans carries all interface and editorial
     text (Chewy appears only in the nav logo lockup). */
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--text);
  background: var(--bg);
}

/* The hidden attribute must always win, even over classes that set display
   (e.g. the admin shell's grid) — without this, "hidden" panels render. */
[hidden] { display: none !important; }

img, svg { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding-left: 1.25rem; }

button { font: inherit; cursor: pointer; }
a { color: var(--brand-text); }
a:hover { color: var(--brand-dark); }

/* ---- Typography ---------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: var(--lh-tight);
  font-weight: 500;
  color: var(--text);
  text-wrap: balance;
}
/* Tracking scales with size: large headings tighten, small ones barely.
   Chinese headings never tighten (see the :lang rules below). */
h1, h2 { color: var(--brand-text); letter-spacing: -0.035em; }
h3, h4 { letter-spacing: -0.01em; }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

/* ---- Traditional Chinese typography rules --------------------------------
   Applied via lang attributes (lang="zh-Hant" on the element or a parent).
   CJK glyphs need no negative tracking and want taller line-height. */
:is(h1, h2, h3, h4, .hero h1):is(:lang(zh), :lang(zh-Hant), :lang(zh-TW)) {
  letter-spacing: 0;
  line-height: 1.25;
}
:is(p, li, dd, .lead, td, th):is(:lang(zh), :lang(zh-Hant), :lang(zh-TW)) {
  line-height: 1.75;
  letter-spacing: 0;
}

/* Financial and numeric data always aligns in columns */
.num, .metric__value, .table td, .table th {
  font-variant-numeric: tabular-nums;
}

.text-soft { color: var(--text-soft); }
.text-sm   { font-size: var(--fs-sm); }
.text-xs   { font-size: var(--fs-xs); }

/* Eyebrow — small sans label above sections: quiet, uppercase, tracked. */
.eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-text);
  margin-bottom: var(--space-3);
}

/* Lead paragraph — one step up from body, for section/page intros. */
.lead {
  font-size: 1.25rem;
  color: var(--text-soft);
  line-height: var(--lh-snug);
  max-width: 58ch;
}

/* ---- Layout primitives --------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-4);
}
.container--narrow { max-width: var(--container-narrow); }
.container--wide { max-width: var(--container-wide); }

/* Large editorial section spacing (for major homepage compositions) */
.section--lg { padding-block: var(--space-9); }

/* Vertical section rhythm */
.section { padding-block: var(--space-7); }
.section + .section { padding-top: 0; }

/* Simple vertical stack spacing helper */
.stack > * + * { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-6); }

/* Responsive auto-fit grid used for card grids */
.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
}

/* ---- Accessibility helpers ---------------------------------------------- */
/* Skip link — first focusable element on every page */
.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -3rem;
  z-index: 100;
  background: var(--brand);
  color: #fff;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  transition: top var(--transition);
}
.skip-link:focus { top: var(--space-2); color: #fff; }

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

/* Visible focus state on all interactive elements. High-contrast yellow band
   with a dark keyline reads on white, dark, and coloured surfaces alike. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus-inset);
  outline-offset: 0;
  box-shadow: 0 0 0 5px var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Loading skeleton — a calm placeholder while data loads. The shimmer is
   disabled under reduced-motion (falls back to a static tint). */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--gray-100);
  border-radius: var(--radius-sm);
  color: transparent !important;
}
.skeleton::after {
  content: "";
  position: absolute; inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
  animation: skeleton-sweep 1.3s infinite;
}
@keyframes skeleton-sweep { 100% { transform: translateX(100%); } }

/* Respect users who prefer reduced motion */
@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;
  }
  .skeleton::after { display: none; }
}
