/*
 * Hash Design System — core
 * ---------------------------------------------------------------
 * The one file every surface loads. It carries the tokens, the base
 * type, and the five signature devices that make a page recognisably
 * ours no matter which kit it belongs to:
 *
 *   1. the five-band strip      Green → Yellow → Orange → Blue → Purple
 *   2. the mono "#" eyebrow     the # in HashHackCode, used as a label
 *   3. the band highlight       a gradient bar behind one headline word
 *   4. the ink pill button      near-black, hovers to band yellow
 *   5. white walls, tinted cards colour lives inside rounded cards
 *
 * Load order on every page:
 *   hash.css → hash-theme.css → hash-ui.css → hash-motion.css   (framework)
 *   hds-core.css                                                (this file)
 *   hds-site.css | hds-doc.css | hds-app.css | hds-print.css    (one or more)
 *   page <style> or project css                                 (last word)
 *
 * Everything here is UNLAYERED, so it outranks the framework's
 * @layer blocks without a single !important.
 */

/* Fonts are bundled, not fetched.
   The upstream HDS file @imports these three families from Google Fonts. A
   workshop runs on room wifi and sometimes behind a school proxy, so the faces
   ship with the theme instead. Same three families, same names, latin subset,
   variable weight axes — every rule below is unchanged. */
@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Manrope';
  src: url('../fonts/manrope.woff2') format('woff2');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('../fonts/jetbrains-mono.woff2') format('woff2');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   1. TOKENS
   Two tiers. Palette tokens name a colour; semantic tokens name a
   job. Only semantic tokens appear in component rules, which is why
   the app desk, the doc page and the A4 sheet can all re-point them
   without touching a single component.
============================================================ */
:root {
  /* ---- type ---- */
  --font-display: 'Montserrat', 'Segoe UI', system-ui, sans-serif;
  --font-primary: 'Manrope', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', monospace;

  /* ---- palette: ink ---- */
  --ink:        #241b2e;
  --ink-2:      #453a52;
  --ink-3:      #6b6178;
  --muted:      #8b8395;

  /* ---- palette: brand (HHC purple) ---- */
  --brand-50:   #faf5fd;
  --brand-100:  #f3e8f9;
  --brand-200:  #e3c9ef;
  --brand-300:  #ce9fe1;
  --brand-400:  #b56dd0;
  --brand-500:  #9f44bc;
  --brand-600:  #85359f;
  --brand-700:  #6e2f86;
  --brand-800:  #56406c;
  --brand:      var(--brand-500);
  --brand-ink:  #7c3798;   /* brand at text contrast on white */
  --on-brand:   #ffffff;

  /* ---- palette: the five curriculum bands ---- */
  --band-green:  #65bd82;
  --band-yellow: #ffdc4c;
  --band-orange: #ff9d32;
  --band-blue:   #4bb7dc;
  --band-purple: #9f44bc;

  /* band tints — the fill of a tinted card */
  --tint-green:  #eaf7ef;
  --tint-yellow: #fff8dd;
  --tint-orange: #fff1e2;
  --tint-blue:   #e8f6fb;
  --tint-purple: #f4ebf8;
  --tint-lav:    #efeafb;

  /* band inks — band colour pushed to text contrast */
  --ink-green:  #2e7d4f;
  --ink-yellow: #8a6a00;
  --ink-orange: #b26a12;
  --ink-blue:   #1b6d86;
  --ink-purple: #7c3798;

  /* ---- palette: status ---- */
  --ok:     #65bd82;  --ok-bg:     #eaf7ef;  --ok-ink:     #2e7d4f;
  --warn:   #ff9d32;  --warn-bg:   #fff1e2;  --warn-ink:   #b26a12;
  --danger: #e05c5c;  --danger-bg: #fdecec;  --danger-ink: #b03a3a;
  --info:   #4bb7dc;  --info-bg:   #e8f6fb;  --info-ink:   #1b6d86;

  /* ---- semantic: surfaces ----
     --paper  the thing content sits on (card, panel, sheet)
     --desk   the thing paper sits on   (page wall, app background)
     --sunken a well inside paper       (search field, code block) */
  --paper:  #ffffff;
  --desk:   #ffffff;
  --sunken: #f7f4fb;
  --raised: #efe9f8;
  --edge:        #eae4f1;
  --edge-strong: #d8cfe4;

  /* ---- semantic: foreground ---- */
  --fg:       var(--ink);
  --fg-2:     var(--ink-2);
  --fg-muted: var(--muted);
  --fg-link:  var(--brand-ink);

  /* ---- radius ---- */
  --rad-xs:   1rem;
  --rad-sm:   1.6rem;
  --rad-md:   2.4rem;
  --rad-lg:   3.2rem;
  --rad-pill: 999px;

  /* ---- shadow ---- */
  --shadow-1: 0 0.2rem 1rem rgba(36, 27, 46, 0.05);
  --shadow-2: 0 1rem 3rem rgba(36, 27, 46, 0.09);
  --shadow-3: 0 2rem 5rem rgba(36, 27, 46, 0.14);
  --shadow-brand: 0 1rem 3rem rgba(159, 68, 188, 0.22);

  /* ---- type scale ----
     1–5 are fixed (UI text stays legible and predictable);
     6–8 clamp (display type answers to the viewport). */
  --fs-1: 1.2rem;
  --fs-2: 1.3rem;
  --fs-3: 1.5rem;
  --fs-4: 1.7rem;
  --fs-5: 2rem;
  --fs-6: clamp(2.2rem, 1vw + 1.8rem, 2.8rem);
  --fs-7: clamp(3rem, 2.2vw + 2rem, 4.6rem);
  --fs-8: clamp(3.6rem, 4vw + 2rem, 6.8rem);

  /* ---- layout ---- */
  --wrap:  120rem;
  --wrap-narrow: 82rem;
  --stick: 9rem;       /* header height = smooth-anchor offset */

  /* ---- motion ---- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-1: 0.18s;
  --dur-2: 0.25s;
  --dur-3: 0.45s;
}

/* ============================================================
   2. BASE
============================================================ */
body {
  font-family: var(--font-primary);
  font-size: var(--fs-4);
  line-height: 1.7;
  color: var(--fg-2);
  background: var(--desk);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  color: var(--fg);
  letter-spacing: -0.025em;
  text-wrap: balance;
}
h1 { font-size: var(--fs-8); line-height: 1.0; }
h2 { font-size: var(--fs-7); line-height: 1.06; }
h3 { font-size: var(--fs-6); line-height: 1.18; letter-spacing: -0.015em; }
h4, h5, h6 {
  font-family: var(--font-primary);
  font-weight: 700;
  color: var(--fg);
  line-height: 1.35;
}
h4 { font-size: var(--fs-5); }
h5 { font-size: var(--fs-4); }
h6 { font-size: var(--fs-3); }

a { color: var(--fg-link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.3em; }
::selection { background: var(--band-yellow); color: var(--ink); }

/* One visible focus ring for the whole system. */
:focus-visible {
  outline: 3px solid var(--brand-500);
  outline-offset: 2px;
  border-radius: 0.4rem;
}

/* ============================================================
   3. SIGNATURE — the five devices
============================================================ */

/* --- 3.1 the mono "#" eyebrow ------------------------------ */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-3);
  font-weight: 500;
  color: var(--brand-ink);
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  align-self: flex-start;      /* .stack is a flex column: opt out of stretch */
  margin: 0 0 1.6rem;
  letter-spacing: 0.01em;
}
.eyebrow::before { content: '#'; font-weight: 700; opacity: 0.55; }
.eyebrow.on-dark { color: var(--band-yellow); }
.eyebrow.sm { font-size: var(--fs-1); }

/* --- 3.2 the five-band strip ------------------------------- */
.bands {
  display: inline-flex;
  gap: 0.5rem;
  height: 0.9rem;
  align-self: flex-start;
}
.bands span { width: 3.4rem; border-radius: var(--rad-pill); }
.bands.wide span { width: 5.4rem; }
.bands.full { display: flex; width: 100%; }
.bands.full span { width: auto; flex: 1; }
.bands span:nth-child(1) { background: var(--band-green); }
.bands span:nth-child(2) { background: var(--band-yellow); }
.bands span:nth-child(3) { background: var(--band-orange); }
.bands span:nth-child(4) { background: var(--band-blue); }
.bands span:nth-child(5) { background: var(--band-purple); }

/* --- 3.3 the band highlight -------------------------------- */
.hl {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  z-index: 0;                  /* own stacking context, so ::before stays local */
}
.hl::before {
  content: '';
  position: absolute;
  inset: auto -0.18em;
  top: 58%;
  height: 0.62em;
  border-radius: 0.24em;
  background: linear-gradient(90deg,
    var(--band-green), var(--band-yellow), var(--band-orange),
    var(--band-blue), var(--band-purple));
  opacity: 0.9;
  transform: translateY(-50%) scaleX(1);
  transform-origin: left;
  z-index: -1;
}
.hl-yellow::before { background: var(--band-yellow); opacity: 1; }
.hl-brand::before  { background: var(--brand-200);   opacity: 1; }

/* Draws itself in when the heading reveals — and only once JS has
   booted, so a no-JS page still shows a finished highlight. */
.hash-ready .hl::before { transform: translateY(-50%) scaleX(0); }
.hash-ready .is-in .hl::before,
.hash-ready .hl.is-in::before,
.hash-ready :not([data-reveal]) > .hl::before {
  transform: translateY(-50%) scaleX(1);
  transition: transform 0.7s var(--ease-out) 0.2s;
}

/* --- 3.4 buttons: one ink pill ----------------------------- */
.btn, .btn-primary, .btn-ghost, .btn-line, .btn-brand {
  font-family: var(--font-primary);
  font-weight: 700;
  font-size: var(--fs-4);
  line-height: 1;
  border-radius: var(--rad-pill);
  padding: 1.6rem 3.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  cursor: pointer;
  border: 2px solid transparent;
  text-decoration: none;
  transition: background var(--dur-2) ease, color var(--dur-2) ease,
              border-color var(--dur-2) ease, transform var(--dur-1) ease;
}
.btn:hover, .btn-primary:hover, .btn-ghost:hover,
.btn-line:hover, .btn-brand:hover { text-decoration: none; }

.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: var(--band-yellow); color: var(--ink); transform: translateY(-2px); }

.btn-brand { background: var(--brand-500); color: #fff; }
.btn-brand:hover { background: var(--band-yellow); color: var(--ink); transform: translateY(-2px); }

.btn-ghost { background: transparent; color: var(--fg); border-color: var(--edge-strong); }
.btn-ghost:hover { border-color: var(--ink); background: var(--paper); }

.btn-soft { background: var(--sunken); color: var(--fg); }
.btn-soft:hover { background: var(--raised); }

.on-dark.btn-ghost { color: #fff; border-color: rgba(255,255,255,.4); }
.on-dark.btn-ghost:hover { background: #fff; color: var(--ink); border-color: #fff; }

.btn-xs { padding: 0.7rem 1.4rem; font-size: var(--fs-1); gap: 0.5rem; }
.btn-sm { padding: 1.1rem 2.2rem; font-size: var(--fs-2); }
.btn-lg { padding: 2rem 4.2rem; font-size: var(--fs-5); }
.btn-block { display: flex; width: 100%; }
[disabled].btn, [disabled].btn-primary, [disabled].btn-brand,
[disabled].btn-ghost, [disabled].btn-soft { opacity: .45; pointer-events: none; }

/* ============================================================
   4. SHARED PRIMITIVES
   Small pieces every kit needs. Kit files add the big ones.
============================================================ */

/* --- icon sprite -------------------------------------------
   <svg class="ico"><use href="img/icons.svg#play"></use></svg>
   Currentcolor throughout, so an icon takes the colour of its row. */
.ico {
  width: 1em;
  height: 1em;
  display: inline-block;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.125em;
}
.ico-fill { fill: currentColor; stroke: none; }
.ico-lg { width: 2.4rem; height: 2.4rem; }
.ico-xl { width: 3.2rem; height: 3.2rem; }

/* icon in a tinted rounded square — the system's default "thumbnail" */
.icon-box {
  width: 5.2rem;
  height: 5.2rem;
  border-radius: var(--rad-xs);
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--sunken);
  color: var(--fg);
  align-self: flex-start;
}
.icon-box .ico { width: 2.4rem; height: 2.4rem; }
.icon-box.sm { width: 4rem; height: 4rem; }
.icon-box.sm .ico { width: 2rem; height: 2rem; }
.icon-box.lg { width: 6.8rem; height: 6.8rem; border-radius: var(--rad-sm); }
.icon-box.lg .ico { width: 3.2rem; height: 3.2rem; }
.icon-box.round { border-radius: 50%; }

/* --- mono glyph -------------------------------------------
   ASCII art in the mono face. The system never uses emoji. */
.glyph {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: var(--fs-4);
  background: var(--paper);
  color: var(--fg);
  border-radius: var(--rad-xs);
  box-shadow: var(--shadow-1);
  padding: 1rem 1.4rem;
  display: inline-block;
  align-self: flex-start;
  line-height: 1;
}

/* --- chip / pill ------------------------------------------- */
/* flex-shrink: 0 — a pill beside a sentence is a flex item, and a flex
   item compresses below its own content by default. A pill's label is
   usually one unbreakable word, so it does not wrap: it spills out of
   the pill and over whatever follows. */
.chip {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.6rem;
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: var(--fs-1);
  font-weight: 500;
  line-height: 1;
  padding: 0.7rem 1.3rem;
  border-radius: var(--rad-pill);
  background: var(--sunken);
  color: var(--fg-2);
  white-space: nowrap;
}
.chip .ico { width: 1.4rem; height: 1.4rem; }
.chip-brand  { background: var(--brand-100); color: var(--brand-ink); }
.chip-ink    { background: var(--ink); color: #fff; }
.chip-line   { background: transparent; border: 1px solid var(--edge-strong); }
.chip-accent { background: var(--tint, var(--sunken)); color: var(--accent-ink, var(--fg-2)); }

/* a chip carrying its band's dot */
.band-tag { display: inline-flex; flex-shrink: 0; align-items: center; gap: 0.6rem;
  font-family: var(--font-mono); font-size: var(--fs-1); font-weight: 500;
  padding: 0.6rem 1.2rem; border-radius: var(--rad-pill);
  background: var(--sunken); color: var(--fg-2); align-self: flex-start; }
.band-tag::before { content: ''; width: 1rem; height: 1rem; border-radius: 50%;
  background: var(--band, var(--band-green)); flex-shrink: 0; }
.band-tag.b-green  { --band: var(--band-green); }
.band-tag.b-yellow { --band: var(--band-yellow); }
.band-tag.b-orange { --band: var(--band-orange); }
.band-tag.b-blue   { --band: var(--band-blue); }
.band-tag.b-purple { --band: var(--band-purple); }

/* --- status dot pill (apps + admin) ------------------------ */
.status {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.6rem;
  align-self: flex-start;
  font-size: var(--fs-1);
  font-weight: 700;
  line-height: 1;
  padding: 0.6rem 1.2rem;
  border-radius: var(--rad-pill);
  white-space: nowrap;
}
.status::before { content: ''; width: 0.8rem; height: 0.8rem; border-radius: 50%;
  background: currentColor; flex-shrink: 0; }
.status.ok    { background: var(--ok-bg);     color: var(--ok-ink); }
.status.warn  { background: var(--warn-bg);   color: var(--warn-ink); }
.status.bad   { background: var(--danger-bg); color: var(--danger-ink); }
.status.info  { background: var(--info-bg);   color: var(--info-ink); }
.status.brand { background: var(--brand-100); color: var(--brand-ink); }
.status.off   { background: var(--sunken);    color: var(--muted); }

/* --- avatar ------------------------------------------------ */
.avatar {
  width: 3.8rem; height: 3.8rem;
  border-radius: 50%;
  object-fit: cover;
  background: var(--brand-100);
  color: var(--brand-ink);
  display: inline-grid;
  place-items: center;
  font-weight: 800;
  font-size: var(--fs-2);
  flex-shrink: 0;
  align-self: flex-start;
}
.avatar.sm { width: 3rem; height: 3rem; font-size: var(--fs-1); }
.avatar.lg { width: 5.6rem; height: 5.6rem; font-size: var(--fs-4); }
.avatar-stack { display: inline-flex; align-self: flex-start; }
.avatar-stack .avatar { border: 2px solid var(--paper); margin-inline-start: -1rem; }
.avatar-stack .avatar:first-child { margin-inline-start: 0; }
/* ONE RULE FOR THE WHOLE SYSTEM: an unclassed inner element is text,
   anything carrying a class is a component. Never write `.thing span`
   — a bare descendant selector is specificity (0,1,1) and beats
   `.avatar`, `.icon-box`, `.chip` and `.status` (all (0,1,0)), which
   turns their `inline-grid`/`inline-flex` into `block` and knocks the
   content out of centre. `:not([class])` keeps text styling on text
   and hands components back to themselves. */
.person { display: flex; align-items: center; gap: 1.1rem; }
.person b { display: block; color: var(--fg); font-size: var(--fs-2); line-height: 1.4; }
.person span:not([class]) { display: block; font-size: var(--fs-1); color: var(--muted); line-height: 1.4; }

/* --- ticked list ------------------------------------------- */
.check { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.check li { position: relative; padding-inline-start: 3.2rem; }
.check li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 0.55em;
  width: 1.8rem; height: 1.8rem;
  transform: translateY(-50%);
  border-radius: 50%;
  background: var(--accent, var(--band-green));
  /* the tick, drawn with a background image so the marker needs no markup */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 1.2rem;
  background-repeat: no-repeat;
  background-position: center;
}

/* --- divider / rules --------------------------------------- */
.rule { border: none; border-top: 1px solid var(--edge); margin: 0; }
.rule-band { border: none; height: 0.4rem; border-radius: var(--rad-pill); margin: 0;
  background: linear-gradient(90deg, var(--band-green), var(--band-yellow),
    var(--band-orange), var(--band-blue), var(--band-purple)); }

/* --- layout utilities --------------------------------------- */
/* `.grow` is the system's one spacer: it pushes everything after it
   to the far end of a flex row. Used in every head, bar and toolbar. */
.grow { margin-inline-start: auto; }
.row-center { display: flex; align-items: center; gap: 1.2rem; }

/* --- text utilities ---------------------------------------- */
.mono { font-family: var(--font-mono); }
.lede { font-size: var(--fs-5); color: var(--fg-2); line-height: 1.6; }
.small { font-size: var(--fs-2); }
.tiny { font-size: var(--fs-1); }
.muted { color: var(--muted); }
.strongink { color: var(--fg); font-weight: 700; }
.upper { text-transform: uppercase; letter-spacing: 0.06em; }
.label {
  font-family: var(--font-mono);
  font-size: var(--fs-1);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

/* --- generic panel (used by doc + app + site) --------------- */
.panel {
  background: var(--paper);
  border: 1px solid var(--edge);
  border-radius: var(--rad-md);
  padding: 2.4rem;
  min-width: 0;
}
.panel-head {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  margin-bottom: 1.8rem;
}
.panel-head h3, .panel-head h4 { margin: 0; font-size: var(--fs-4); font-weight: 800; }
.panel-head .grow { margin-inline-start: auto; }
.panel-pad-sm { padding: 1.8rem; }
.panel-flat { border: none; box-shadow: var(--shadow-1); }

/* ============================================================
   4b. TINTS
   The class is written twice on purpose. `.t-purple` on its own is a
   single-class selector, and so is `.card`, `.panel` and `.icon-box`
   — whichever stylesheet loads last would win, which made the tint
   depend on file order. `.t-purple.t-purple` is specificity (0,2,0)
   and always beats the component's own background, in every layer,
   in any load order.
============================================================ */
.t-green.t-green   { background: var(--tint-green);  --accent: var(--band-green);  --accent-ink: var(--ink-green);  --tint: var(--tint-green); }
.t-yellow.t-yellow { background: var(--tint-yellow); --accent: var(--band-yellow); --accent-ink: var(--ink-yellow); --tint: var(--tint-yellow); }
.t-orange.t-orange { background: var(--tint-orange); --accent: var(--band-orange); --accent-ink: var(--ink-orange); --tint: var(--tint-orange); }
.t-blue.t-blue     { background: var(--tint-blue);   --accent: var(--band-blue);   --accent-ink: var(--ink-blue);   --tint: var(--tint-blue); }
.t-purple.t-purple { background: var(--tint-purple); --accent: var(--band-purple); --accent-ink: var(--ink-purple); --tint: var(--tint-purple); }
.t-lav.t-lav       { background: var(--tint-lav);    --accent: var(--brand-400);   --accent-ink: var(--brand-ink);  --tint: var(--tint-lav); }
.t-ink.t-ink       { background: var(--ink); color: rgba(255,255,255,.78); --accent: var(--band-yellow); --accent-ink: var(--band-yellow); }
.t-ink h1, .t-ink h2, .t-ink h3, .t-ink h4, .t-ink b, .t-ink strong { color: #fff; }

/* ============================================================
   4c. NARROW-SCREEN REVEAL SAFETY
   A horizontal reveal starts 3rem off to one side. At desktop width
   that is invisible; at 390px it is 30px of horizontal page scroll on
   every page that uses one, because the element is still in its start
   state below the fold. Side reveals become vertical reveals where
   there is no room for them.
============================================================ */
@media (max-width: 900px) {
  :where(.hash-ready) [data-reveal="left"],
  :where(.hash-ready) [data-reveal="right"] {
    transform: translateY(var(--reveal-shift, 3rem));
  }
}

/* ============================================================
   5. PRINT SAFETY
   Any surface may be printed. Keep colour, drop chrome.
============================================================ */
@media print {
  .no-print { display: none !important; }
  body { background: #fff; }
  a { color: inherit; text-decoration: none; }
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ============================================================
   6. REDUCED MOTION
============================================================ */
@media (prefers-reduced-motion: reduce) {
  .hash-ready .hl::before { transform: translateY(-50%) scaleX(1); transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
