/* ==========================================================================
   Object-Oriented JavaScript — the design system.

   Quiet by intent. One typeface, one accent, a single measured column, hairline
   rules instead of boxes, and no ornament anywhere. Everything that looks like
   a decision here is about making three hours of reading comfortable: the
   measure, the leading, the spacing scale, and the contrast of the code panels
   against the page.

   Light and dark are both first-class and follow the reader's system setting.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Surfaces, from the page backward. */
  --bg: #ffffff;
  --bg-subtle: #f7f7f8;
  --bg-sunken: #f2f2f4;
  --bg-code: #fbfbfc;

  /* Text, from most to least prominent. */
  --fg: #17171a;
  --fg-muted: #5c5c66;
  --fg-faint: #71717c;

  /* Lines. */
  --line: #e6e6ea;
  --line-strong: #d0d0d7;
  /* A control whose border is the only thing identifying it needs 3:1 against
     the page, which --line-strong does not reach. Decorative rules keep using
     --line and --line-strong; anything operable uses this. */
  --border-control: #8e8e98;

  /* One accent, used for links, focus and the primary action. */
  --accent: #3055d8;
  --accent-hover: #2543b4;
  --accent-fg: #ffffff;
  --accent-subtle: #eef1fd;

  /* Two states, used sparingly and never alone. */
  --ok: #17734b;
  --ok-subtle: #eaf6ef;
  --warn: #a3341f;
  --warn-subtle: #fdefec;

  /* Type. */
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --t-hero: clamp(2.25rem, 4.6vw, 3.25rem);
  --t-h1: clamp(1.875rem, 3.4vw, 2.5rem);
  --t-h2: 1.5rem;
  --t-h3: 1.125rem;
  --t-lede: 1.1875rem;
  --t-body: 1.0625rem;
  --t-small: 0.9375rem;
  --t-label: 0.8125rem;
  --t-mono: 0.875rem;

  /* Spacing, on a 4px grid. */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;

  --radius: 8px;
  --radius-sm: 6px;

  /* One column, one left edge. The header, the hero, every section and the
     footer all use --shell, so nothing on the page is inset differently from
     anything else. Paragraphs cap at --measure inside it, which shortens the
     line without moving the left edge. */
  --shell: 828px;
  --measure: 68ch;

  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101013;
    --bg-subtle: #17171b;
    --bg-sunken: #1c1c21;
    --bg-code: #16161a;

    --fg: #ececf1;
    --fg-muted: #a1a1ad;
    --fg-faint: #8b8b98;

    --line: #26262d;
    --line-strong: #35353e;
    --border-control: #63636e;

    --accent: #8ba4ff;
    --accent-hover: #a8bbff;
    --accent-fg: #101013;
    --accent-subtle: #1a1f33;

    --ok: #6fc79c;
    --ok-subtle: #14231b;
    --warn: #ffa494;
    --warn-subtle: #2a1815;
  }
}

/* ---------- 2. Reset ---------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--s8);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.7;
  font-feature-settings: 'cv05' 1, 'cv08' 1, 'ss01' 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

button {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  top: var(--s2);
  left: 50%;
  z-index: 90;
  translate: -50% -200%;
  padding: var(--s2) var(--s4);
  border-radius: var(--radius-sm);
  background: var(--fg);
  color: var(--bg);
  font-size: var(--t-label);
  font-weight: 500;
  text-decoration: none;
  transition: translate 0.2s var(--ease);
}

.skip:focus-visible {
  translate: -50% 0;
}

/* ---------- 3. Header --------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  max-width: var(--shell);
  margin-inline: auto;
  padding: var(--s3) var(--s5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s5);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--fg);
  text-decoration: none;
  white-space: nowrap;
}

.wordmark__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--s1);
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav a {
  display: block;
  padding: var(--s1) var(--s3);
  border-radius: var(--radius-sm);
  font-size: var(--t-label);
  font-weight: 500;
  color: var(--fg-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s var(--ease), background-color 0.15s var(--ease);
}

.site-nav a:hover {
  color: var(--fg);
  background: var(--bg-subtle);
}

.site-nav a[aria-current='page'] {
  color: var(--fg);
  background: var(--bg-sunken);
}

/* ---------- 4. Page frame ----------------------------------------------- */

.page {
  max-width: var(--shell);
  margin-inline: auto;
  padding: var(--s8) var(--s5) var(--s9);
}

/* A section that continues the page rather than opening it. */
.section {
  max-width: var(--shell);
  margin-inline: auto;
  padding: 0 var(--s5) var(--s8);
}

.section > :where(h2):first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ---------- 5. Typography ----------------------------------------------- */

.prose :where(h1, h2, h3) {
  color: var(--fg);
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin: 0;
}

.prose :where(h1) {
  font-size: var(--t-h1);
  font-weight: 600;
  line-height: 1.15;
}

.prose :where(h2) {
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.3;
  margin-block: var(--s8) var(--s4);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
}

.prose :where(h3) {
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.011em;
  margin-block: var(--s6) var(--s3);
}

.prose :where(p) {
  max-width: var(--measure);
  margin-block: 0 var(--s4);
}

.prose :where(ul, ol) {
  max-width: var(--measure);
  margin-block: 0 var(--s5);
  padding-left: var(--s5);
}

.prose :where(li) {
  margin-bottom: var(--s2);
  padding-left: var(--s1);
}

.prose :where(li)::marker {
  color: var(--fg-faint);
}

.prose :where(strong) {
  font-weight: 600;
}

.prose :where(a) {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color 0.15s var(--ease);
}

.prose :where(a):hover {
  color: var(--accent-hover);
}

/* Inline code: quiet, and never wider than the line it sits on. */
.prose :where(code):not([class]) {
  font-family: var(--mono);
  font-size: 0.875em;
  padding: 0.15em 0.36em;
  background: var(--bg-sunken);
  border-radius: 4px;
  white-space: nowrap;
}

.lede {
  max-width: 64ch;
  font-size: var(--t-lede);
  line-height: 1.6;
  color: var(--fg-muted);
  margin: var(--s4) 0 0;
}

.label {
  font-size: var(--t-label);
  font-weight: 500;
  color: var(--fg-faint);
  letter-spacing: 0;
}

/* ---------- 6. Page head ------------------------------------------------ */

.head {
  margin-bottom: var(--s7);
}

.head__meta {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 0 0 var(--s4);
  font-size: var(--t-label);
  color: var(--fg-faint);
}

.head__meta span + span::before {
  content: '·';
  margin-right: var(--s3);
  color: var(--line-strong);
}

.head h1 {
  font-size: var(--t-h1);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.024em;
  margin: 0;
  text-wrap: balance;
}

.head__goal {
  display: flex;
  gap: var(--s3);
  margin: var(--s5) 0 0;
  max-width: 64ch;
  padding: var(--s4);
  max-width: 62ch;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  font-size: var(--t-small);
  color: var(--fg-muted);
}

.head__goal strong {
  flex: none;
  white-space: nowrap;
  color: var(--fg);
  font-weight: 500;
}

/* ---------- 7. Code panel ----------------------------------------------- */

.code {
  margin-block: var(--s5) var(--s6);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-code);
  overflow: hidden;
}

.code__bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s2) var(--s2) var(--s4);
  border-bottom: 1px solid var(--line);
}

.code__name {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: var(--t-label);
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.code__body {
  margin: 0;
  padding: var(--s4) 0;
  display: grid;
  grid-template-columns: auto 1fr;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.7;
  tab-size: 2;
}

.code__nums {
  padding-inline: var(--s4) var(--s3);
  text-align: right;
  color: var(--fg-faint);
  opacity: 0.55;
  user-select: none;
  font-variant-numeric: tabular-nums;
}

.code__src {
  padding-right: var(--s4);
  white-space: pre;
  min-width: 0;
}

.code__edit {
  display: block;
  width: 100%;
  min-height: 200px;
  padding: var(--s4);
  border: none;
  background: transparent;
  color: var(--fg);
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.7;
  tab-size: 2;
  resize: vertical;
}

.code__edit:focus-visible {
  outline-offset: -2px;
}

/* Output */
.out {
  border-top: 1px solid var(--line);
  background: var(--bg-subtle);
}

.out__label {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin: 0;
  padding: var(--s2) var(--s4);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--fg-faint);
}

.out__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line-strong);
  flex: none;
  transition: background-color 0.2s var(--ease);
}

.code[data-state='ran'] .out__dot {
  background: var(--ok);
}

.code[data-state='threw'] .out__dot {
  background: var(--warn);
}

.out__body {
  margin: 0;
  padding: 0 var(--s4) var(--s4);
  font-family: var(--mono);
  font-size: var(--t-mono);
  line-height: 1.65;
  color: var(--fg);
  white-space: pre-wrap;
  overflow-x: auto;
  min-height: 1.65em;
}

.out__body:empty::after {
  content: 'Press Run to see the output.';
  font-family: var(--sans);
  font-size: var(--t-label);
  color: var(--fg-faint);
}

.ln {
  display: block;
}

.ln--warn {
  color: var(--warn);
}

.ln--err {
  color: var(--warn);
}

.ln--ret {
  color: var(--fg-muted);
}

.ln--ret::before {
  content: '⤶ ';
  opacity: 0.6;
}

/* Syntax. Restrained: three hues plus muted comments. */
.t-key { color: #8250df; }
.t-this { color: #8250df; font-style: italic; }
.t-cls { color: #953800; }
.t-str { color: #0a6b57; }
.t-num { color: #0550ae; }
.t-com { color: var(--fg-muted); }
.t-fn { color: #6639ba; }
.t-prop { color: var(--fg); }
.t-priv { color: #953800; }
.t-pun { color: var(--fg-muted); }

@media (prefers-color-scheme: dark) {
  .t-key { color: #d2a8ff; }
  .t-this { color: #d2a8ff; font-style: italic; }
  .t-cls { color: #ffa657; }
  .t-str { color: #7ee0c0; }
  .t-num { color: #96caff; }
  .t-com { color: var(--fg-muted); }
  .t-fn { color: #d2a8ff; }
  .t-prop { color: var(--fg); }
  .t-priv { color: #ffa657; }
  .t-pun { color: var(--fg-muted); }
}

/* ---------- 8. Buttons -------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: 7px var(--s3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--fg);
  color: var(--bg);
  font-size: var(--t-label);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: opacity 0.15s var(--ease), background-color 0.15s var(--ease),
    border-color 0.15s var(--ease), color 0.15s var(--ease);
}

.btn:hover {
  opacity: 0.86;
}

.btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

.btn--quiet {
  background: transparent;
  border-color: var(--border-control);
  color: var(--fg-muted);
}

.btn--quiet:hover {
  opacity: 1;
  background: var(--bg-subtle);
  color: var(--fg);
}

.btn--accent {
  background: var(--accent);
  color: var(--accent-fg);
}

.btn--lg {
  padding: 11px var(--s5);
  font-size: var(--t-small);
}

.btn svg {
  width: 14px;
  height: 14px;
  flex: none;
}

/* ---------- 9. Callouts ------------------------------------------------- */

.note {
  margin-block: var(--s5);
  max-width: var(--measure);
  padding: var(--s4) var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-subtle);
}

.note > *:last-child {
  margin-bottom: 0;
}

.note__title {
  display: block;
  margin-bottom: var(--s2);
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--fg);
}

.note--warn {
  background: var(--warn-subtle);
  border-color: color-mix(in srgb, var(--warn) 24%, transparent);
}

.note--warn .note__title {
  color: var(--warn);
}

.note--key {
  background: var(--accent-subtle);
  border-color: color-mix(in srgb, var(--accent) 26%, transparent);
}

.note--key .note__title {
  color: var(--accent);
}

/* ---------- 10. Task ---------------------------------------------------- */

.task {
  margin-block: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
}

.task__title {
  margin: 0 0 var(--s3);
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.011em;
}

/* ---------- 11. Takeaways ----------------------------------------------- */

.recap {
  margin-top: var(--s8);
  padding: var(--s6);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-subtle);
}

.recap h3 {
  margin: 0 0 var(--s4);
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--fg-faint);
}

.recap ul {
  margin: 0;
  padding-left: var(--s5);
}

.recap li {
  margin-bottom: var(--s3);
}

.recap li:last-child {
  margin-bottom: 0;
}

.recap li::marker {
  color: var(--accent);
}

/* ---------- 12. Footer / pager ------------------------------------------ */

.pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
  margin-top: var(--s8);
  padding-top: var(--s6);
  border-top: 1px solid var(--line);
}

.pager__link {
  display: block;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--fg);
  transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease);
}

.pager__link:hover {
  border-color: var(--line-strong);
  background: var(--bg-subtle);
}

.pager__link--next {
  text-align: right;
}

.pager__dir {
  display: block;
  font-size: var(--t-label);
  color: var(--fg-faint);
  margin-bottom: var(--s1);
}

.pager__name {
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: -0.011em;
}

.pager__link:hover .pager__name {
  color: var(--accent);
}

.pager__spacer {
  display: block;
}

.done {
  display: flex;
  align-items: center;
  gap: var(--s4);
  flex-wrap: wrap;
  margin-top: var(--s6);
}

.done__hint {
  margin: 0;
  font-size: var(--t-label);
  color: var(--fg-faint);
}

.site-footer {
  border-top: 1px solid var(--line);
  margin-top: var(--s9);
}

.site-footer__inner {
  max-width: var(--shell);
  margin-inline: auto;
  padding: var(--s6) var(--s5);
  display: flex;
  gap: var(--s5);
  flex-wrap: wrap;
  justify-content: space-between;
  font-size: var(--t-label);
  color: var(--fg-faint);
}

.site-footer a {
  color: var(--fg-muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* ---------- 13. Reduced motion ------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---------- 14. Narrow -------------------------------------------------- */

@media (max-width: 860px) {
  :root {
    --s8: 44px;
    --s9: 64px;
  }

  .site-header__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s3);
    padding-inline: var(--s4);
  }

  .site-nav {
    margin-left: -8px;
  }

  .page,
  .site-footer__inner {
    padding-inline: var(--s4);
  }

  .pager {
    grid-template-columns: 1fr;
  }

  .pager__link--next {
    text-align: left;
  }

  .recap {
    padding: var(--s5) var(--s4);
  }

  .note {
    padding: var(--s4);
  }
}

@media (max-width: 560px) {
  .code__body {
    font-size: 0.8125rem;
  }
}

/* ---------- 15. Print --------------------------------------------------- */

@media print {
  .site-header,
  .pager,
  .btn,
  .skip,
  .out {
    display: none;
  }

  body {
    background: #fff;
    color: #000;
  }

  .code {
    border-color: #bbb;
  }
}
