/* =========================================================================
   Kodyfier — Practice (Skill Tests + Code Lab)
   Design tokens + shared primitives.

   One committed dark theme, matching the Kodyfier Practice reference design:
   near-black surfaces, a mint accent, Poppins for text and JetBrains Mono for
   figures and code. There is deliberately no light scheme — the assessment
   screens are designed around this contrast.
   ========================================================================= */

/* ------------------------------------------------------------------ fonts */

/* Self-hosted latin subsets (SIL Open Font License), identical to the files
   Google Fonts served. From this origin, first paint no longer waits on a
   render-blocking third-party stylesheet and two extra TLS handshakes.
   Characters outside the range fall back to the system stacks below, exactly
   as they did with the Google-hosted subset. */
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/poppins-400.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+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/poppins-500.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+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/poppins-600.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+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/poppins-700.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+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* One variable file covers every weight Google served (400–600). */
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/jetbrains-mono.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+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: dark;

  /* Surfaces */
  --bg: #0a0b0a;
  --surface: #111311;
  --surface-2: #0e100e;
  --surface-sunken: #171a17;
  --surface-hover: #141614;

  /* Ink */
  --ink: #eaefea;
  --ink-2: #a8b0a9;
  --ink-3: #8e978f;
  --ink-4: #6e766f;

  /* Lines */
  --line: #1b1e1c;
  --line-strong: #292d2a;

  /* Accents */
  --accent: #7de2b0;
  --accent-hover: #98eac1;
  --accent-soft: #14251d;
  --accent-line: #2e4d3d;
  --accent-ink: #08150f;

  --danger: #f0897f;
  --danger-soft: #2b1a18;
  --warn: #e5ce7b;
  --warn-soft: #272214;
  --ok: #7de2b0;
  --ok-soft: #14251d;

  /* Shape */
  --r-sm: 8px;
  --r-md: 10px;
  --r-lg: 16px;
  --r-full: 999px;

  /* Elevation — restrained, never glossy */
  --shadow-1: 0 1px 2px rgb(0 0 0 / 30%);
  --shadow-2: 0 16px 40px -18px rgb(0 0 0 / 70%);

  /* Type — Poppins carries the interface, JetBrains Mono every figure,
     label and code fragment. */
  --font-display: "Poppins", ui-sans-serif, system-ui, "Segoe UI", Roboto,
    Arial, sans-serif;
  --font-sans: "Poppins", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono",
    "Fira Code", Consolas, "Liberation Mono", monospace;

  /* Rhythm */
  --step: 4px;
  --gutter: clamp(18px, 4vw, 28px);
  --measure: 1200px;
}

/* ------------------------------------------------------------------ reset */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

/* The `hidden` attribute must beat any layout `display` a component sets,
   otherwise elements toggled via `el.hidden` stay on screen. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg {
  display: block;
  max-width: 100%;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  text-wrap: balance;
}

/* Display-face elements that are not <h*> tags: the wordmark, and the large
   figures that act as headings (score, timer, KPI values). */
.brand__text,
.fact__value,
.stat__value,
.kpi__value,
.timer__value,
.score-card__score,
.score-card__pct,
.leader__score {
  font-family: var(--font-display);
}

p {
  text-wrap: pretty;
}

a {
  color: var(--accent);
  text-underline-offset: 3px;
}

/* Visible, consistent focus for keyboard users everywhere. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  margin: -1px;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------- layout */

.shell {
  width: min(var(--measure), 100%);
  padding-inline: var(--gutter);
  margin-inline: auto;
}

.shell--narrow {
  width: min(760px, 100%);
}

.stack > * + * {
  margin-top: var(--flow, 16px);
}

/* ------------------------------------------------------------- breadcrumb */

/* Low-weight trail for the normal (non-editor) pages: no card, no pill, no
   background — a hairline rule is the only container it gets. */
.crumbs {
  /* One step lighter than --line-strong: the chevrons must stay readable
     without competing with the labels. */
  --crumb-sep: #39423e;
  margin-bottom: clamp(20px, 3vw, 28px);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--crumb-line, var(--line));
}

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 9px;
  padding: 0;
  font-size: 12.5px;
  letter-spacing: 0.005em;
  list-style: none;
}

.crumbs__item {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 8px;
}

/* Truncation is visual only — the element still carries the full label, so
   screen readers and the tooltip read the whole thing. */
.crumbs__link,
.crumbs__context,
.crumbs__label {
  overflow: hidden;
  max-width: min(32ch, 44vw);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.crumbs__link,
.crumbs__context {
  color: var(--ink-3);
}

.crumbs__link {
  padding: 3px 2px;
  border-radius: var(--r-sm);
  text-decoration: none;
  transition: color 0.16s ease;
}

/* Colour alone never carries the affordance: the underline comes with it. */
.crumbs__link:hover,
.crumbs__link:focus-visible {
  color: var(--accent-hover);
  text-decoration: underline;
}

.crumbs__sep {
  flex: none;
  color: var(--crumb-sep);
  font-size: 13px;
  line-height: 1;
}

.crumbs__item--current {
  gap: 7px;
  color: var(--ink);
  font-weight: 600;
}

.crumbs__dot {
  flex: none;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

/* Narrow screens: the trail stays on one line and scrolls inside itself
   rather than wrapping into a two-line block. Every level is kept — Code Lab
   sits at the start, so the route that matters is visible without scrolling.
   The vertical padding is there to stop overflow clipping the focus ring. */
@media (max-width: 560px) {
  .crumbs {
    padding-bottom: 14px;
  }

  .crumbs__list {
    flex-wrap: nowrap;
    gap: 7px;
    padding-block: 4px;
    margin-block: -4px;
    overflow-x: auto;
    font-size: 12px;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .crumbs__list::-webkit-scrollbar {
    display: none;
  }

  .crumbs__item {
    flex: none;
  }

  .crumbs__link,
  .crumbs__context,
  .crumbs__label {
    max-width: min(14ch, 32vw);
  }
}

/* ---------------------------------------------------------------- brand */

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
}

.brand__mark {
  display: grid;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  place-items: center;
}

.brand__text {
  font-size: 15px;
}

.brand__sub {
  color: var(--ink-3);
  font-weight: 400;
}

/* ----------------------------------------------------------------- tabs */

/* Used as <button>s in the admin dashboard and as <a>s in the student
   sub-navigation, so both element types have to look identical. */

.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar {
  display: none;
}

.tab {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 12px 16px 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: none;
  color: var(--ink-3);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    color 0.15s ease,
    border-color 0.15s ease;
}

.tab:hover {
  color: var(--ink);
}

.tab[aria-current="page"] {
  border-bottom-color: var(--accent);
  color: var(--ink);
}

/* A tab the teacher has not released yet: visible, so students know it is
   coming, but inert. */
.tab--locked {
  opacity: 0.55;
  cursor: not-allowed;
}

.tab--locked:hover {
  color: var(--ink-3);
}

.tab__lock {
  margin-left: 5px;
  font-size: 11px;
}

/* ---------------------------------------------------------------- cards */

.card {
  padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.card--flush {
  padding: 0;
  overflow: hidden;
}

/* -------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 12px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 0.16s ease,
    border-color 0.16s ease,
    color 0.16s ease,
    transform 0.16s ease;
}

.btn:hover:not(:disabled) {
  background: var(--accent-hover);
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn--block {
  width: 100%;
}

.btn--lg {
  min-height: 50px;
  padding: 14px 24px;
  font-size: 15px;
}

.btn--ghost {
  border-color: var(--line-strong);
  background: transparent;
  color: var(--ink);
}

.btn--ghost:hover:not(:disabled) {
  border-color: var(--accent);
  background: transparent;
  color: var(--accent);
}

/* The reference's second-tier action: mint on a mint wash, used where a
   card offers a real action that is not the page's primary one. */
.btn--soft {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent);
}

.btn--soft:hover:not(:disabled) {
  border-color: var(--accent);
  background: #17301f;
  color: var(--accent);
}

.btn--danger {
  background: var(--danger);
  color: #fff;
}

.btn--danger:hover:not(:disabled) {
  background: var(--danger);
  filter: brightness(0.92);
}

.btn--sm {
  min-height: 34px;
  padding: 6px 12px;
  font-size: 13px;
}

/* --------------------------------------------------------------- fields */

.field {
  display: block;
}

.field__label {
  display: block;
  margin-bottom: 6px;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.field__hint {
  margin-top: 6px;
  color: var(--ink-3);
  font-size: 12.5px;
}

.input {
  width: 100%;
  min-height: 46px;
  padding: 11px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font-size: 15px;
  transition:
    border-color 0.16s ease,
    box-shadow 0.16s ease;
}

.input::placeholder {
  color: var(--ink-3);
}

.input:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.input[aria-invalid="true"] {
  border-color: var(--danger);
}

/* --------------------------------------------------------------- pieces */

.eyebrow {
  color: var(--ink-4);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: rgb(255 255 255 / 4%);
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
  text-transform: uppercase;
}

.pill--ok {
  border-color: transparent;
  background: var(--ok-soft);
  color: var(--ok);
}

.pill--warn {
  border-color: transparent;
  background: var(--warn-soft);
  color: var(--warn);
}

.pill--danger {
  border-color: transparent;
  background: var(--danger-soft);
  color: var(--danger);
}

.code {
  padding: 14px 16px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-sunken);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 13.5px;
  line-height: 1.65;
  tab-size: 2;
  white-space: pre;
}

.muted {
  color: var(--ink-3);
}

.divider {
  height: 1px;
  border: 0;
  background: var(--line);
}

/* --------------------------------------------------------------- toast */

.toast {
  position: fixed;
  bottom: 20px;
  left: 50%;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(440px, calc(100vw - 32px));
  padding: 12px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  color: var(--ink);
  font-size: 14px;
  transform: translate(-50%, 16px);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.2s ease,
    transform 0.2s ease;
}

.toast[data-visible="true"] {
  transform: translate(-50%, 0);
  opacity: 1;
}

.toast[data-tone="error"] {
  border-color: var(--danger);
  color: var(--danger);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
