/* --- Fonts --- */
/* Note: Best practice is to use actual bold versions of fonts, mainly for the
sake of appearance, but also for performance, rather than asking the browser to
fake boldness (use "synthetic bold" as it's called) by applying weight 700 to an
inherently 400 font. This can result in fuzzy letters. However, neither of these
fonts is available in bold and appearance and performance seem fine to me. */
@font-face {
  font-family: "Neucha";
  src: url("../assets/fonts/Neucha-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Macondo";
  src: url("../assets/fonts/Macondo-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* --- Tokens --- */
:root {
  /* Stacking order (meaningful only vs siblings / same stacking context). */
  --z-maze: 0;
  --z-main: 1;
  --z-hero-image: 1;
  --z-carousel-arrow: 2;
  /* Hamburger + #site-menu above other in-main content (siblings under main). */
  --z-menu-wrap: 10;
  /* #site-menu inside .menu-wrap: 1 avoids auto vs negative edge cases; still only sorts inside the wrap. */
  --z-site-menu: 1;

  /* Blur on .dialog__scrim, not dialog::backdrop (Chrome ignores blur() there);
  see `04-dialog-contact.css`. */
  --dialog-backdrop-blur: 3px;

  /* Maze */
  --tile-size: 12px;

  /*
   * Font contexts (swap stacks to try typefaces; first family should match an
   * @font-face above, or use a system / web-safe stack you prefer).
   *   --font-stack-ui       titles, buttons, nav, page chrome, default body weight.
   *   --font-stack-prose    dialog body copy, download page note.
   *   --font-stack-download platform labels on the downloads view.
   */
  --font-stack-ui: "Neucha", fantasy, serif;
  --font-stack-prose: "Macondo", fantasy, serif;
  --font-stack-download: "Macondo", fantasy, serif;

  /*
   * Typography scale (rem / weights). Menu cards, dialog chrome, contact
   * labels, and hero CTAs share --font-size-accent (+ -wide at >=768px in
   * each sheet). Contact fields use --font-size-contact-control* (separate).
   * Single-weight webfonts use synthetic bold where needed.
   */
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;

  --font-size-btn: 0.9375rem;
  --font-size-btn-primary: 1rem;

  --font-size-accent: 1.0625rem;
  --font-size-accent-wide: 1.125rem;

  --font-size-dialog-title: 1.55rem;
  --font-size-dialog-title-wide: 1.75rem;
  --font-size-dialog-body: 1.2rem;

  /* Inputs / textarea only (larger than accent labels & dialog chrome). */
  --font-size-contact-control: 1.2rem;
  --font-size-contact-control-wide: 1.3rem;
  --font-weight-contact-control: var(--font-weight-bold);

  --font-weight-cta-primary: var(--font-weight-bold);
  --font-weight-menu-card: var(--font-weight-bold);
  --font-weight-dialog-title: var(--font-weight-extrabold);
  --font-weight-dialog-close: var(--font-weight-bold);
  --font-weight-contact-label: var(--font-weight-bold);
  --font-weight-field-required-mark: var(--font-weight-regular);
  --font-weight-contact-status: var(--font-weight-medium);
  --font-weight-contact-status-error: var(--font-weight-semibold);
  --font-weight-contact-submit: var(--font-weight-bold);

  --letter-spacing-dialog-title: 0.055em;
  --letter-spacing-dialog-close: 0.03em;
  --letter-spacing-ui-caps: 0.04em;

  /* Colors
   *
   * Note: All mixes use oklch; strictly speaking, alpha compositing is done in
   * RGB, but oklch is adequate for our purposes. Having no requirement for
   * general precision, the complexity of converting to RGB and back again
   * didn't seem worth it.
   *
   * Derivation:
   * - Opaque on --color-bg: color-mix when the surface is always page or dialog
   *   background (--color-control-bg, --color-ink-wall,
   *   --color-menu-toggle-hover-bg).
   * - Translucent over a varying backdrop: oklch(from ... / alpha) for hovers,
   *   borders, overlays, and shadows that must blend with content below the
   *   element.
   * - Two opaque theme colors: color-mix without transparency
   *   (--color-error-*). */
  --color-bg: oklch(0.829 0.071 68.669);
  --color-ink: oklch(0.212 0.026 44.064);
  --color-ink-muted: oklch(0.4 0.051 45.932);
  --color-ink-faint-a: 0.17;
  --color-ink-faint: oklch(
    from var(--color-ink) l c h / var(--color-ink-faint-a)
  );
  --color-ink-wall-mix: 7%;
  --color-ink-wall: color-mix(
    in oklch,
    var(--color-ink) var(--color-ink-wall-mix),
    var(--color-bg)
  );
  --color-ink-overlay: oklch(0.164 0.016 48.467 / 0.7);
  --color-ink-hover-a: 0.08;
  --color-ink-hover: oklch(
    from var(--color-ink) l c h / var(--color-ink-hover-a)
  );
  --color-ink-border-strong-a: 0.29;
  --color-ink-border-strong: oklch(
    from var(--color-ink) l c h / var(--color-ink-border-strong-a)
  );
  --color-primary-hover: oklch(0.339 0.054 42.133);
  --color-transparent: oklch(0 0 0 / 0);
  --color-error: oklch(0.579 0.172 24.266);
  --color-error-border: color-mix(
    in oklch,
    var(--color-ink) 60%,
    var(--color-error)
  );
  --color-error-text: color-mix(
    in oklch,
    var(--color-ink) 55%,
    var(--color-error)
  );
  --color-focus-ring: oklch(from var(--color-ink) l c h / 0.28);
  --color-control-bg: color-mix(
    in oklch,
    var(--color-bg) 92%,
    var(--color-ink)
  );
  --color-btn-shadow: oklch(from var(--color-ink) l c h / 0.34);
  --color-btn-shadow-hover: oklch(from var(--color-ink) l c h / 0.44);
  --color-menu-toggle-hover-bg: color-mix(
    in oklch,
    var(--color-bg) 88%,
    var(--color-ink)
  );
  --color-hero-text-shadow-bg: oklch(from var(--color-bg) l c h / 0.75);
  --color-hero-text-shadow-ink: oklch(from var(--color-ink) l c h / 0.42);
  --font-display: var(--font-stack-ui);
  --font-body: var(--font-stack-ui);
  --font-dialog-body: var(--font-stack-prose);
  --button-text-nudge-y: 0.1em;
  --shadow-soft: 0 12px 40px oklch(0.207 0.008 67.392 / 0.12);
  --radius-image: 6px;
  --radius-btn: 4px;
  --carousel-arrow-border: oklch(0.823 0.074 65.815 / 0.38);
  --carousel-arrow-bg: oklch(0.182 0.021 45.35 / 0.94);
  --carousel-arrow-color: oklch(0.823 0.074 65.815);
  --carousel-arrow-shadow:
    0 0 0 2px oklch(0.182 0.021 45.35 / 0.76), 0 4px 12px oklch(0 0 0 / 0.46),
    0 14px 34px oklch(0 0 0 / 0.75);
  --carousel-arrow-hover-bg: oklch(0.324 0.053 46.184 / 0.95);
  --carousel-arrow-hover-border: oklch(0.868 0.062 64.461 / 0.66);
  --carousel-arrow-hover-shadow:
    0 0 0 2px oklch(0.182 0.021 45.35 / 0.85), 0 6px 14px oklch(0 0 0 / 0.55),
    0 18px 38px oklch(0 0 0 / 0.81);
  --carousel-arrow-focus-outline: oklch(0.823 0.074 65.815);
  --color-selection-bg-a: 0.22;
  --color-selection-bg: oklch(
    from var(--color-ink) l c h / var(--color-selection-bg-a)
  );
  --color-selection-fg: var(--color-ink);

  /* Meander tiles: stroke #000 (mask stencil, not a theme token): oklch(0 0 0).
  Ink color comes from background-color on ::before. SVG data URIs cannot read CSS
  variables, so the stroke stays hex; otherwise each theme would need its own
  meander URLs as with --corner-theta. */
  --meander-tile-h-top: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -2 25 20'%3E%3Cpath d='M0,15 H5 V0 H20 V10 H15 V5 H10 V15 H25' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'/%3E%3C/svg%3E");
  --meander-tile-h-bottom: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -2 25 20'%3E%3Cpath d='M0,1 H5 V16 H20 V6 H15 V11 H10 V1 H25' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'/%3E%3C/svg%3E");
  --meander-tile-v-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-2 0 20 25'%3E%3Cpath d='M15,0 V15 H5 V10 H10 V5 H0 V20 H15 V25' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'/%3E%3C/svg%3E");
  --meander-tile-v-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-2 0 20 25'%3E%3Cpath d='M1,0 V15 H11 V10 H6 V5 H16 V20 H1 V25' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='butt' stroke-linejoin='miter'/%3E%3C/svg%3E");
  /* Corner theta (light): fill #e6bf95 (--color-bg): oklch(0.829 0.071 68.669).
  Must match --color-bg; SVG data URIs cannot read CSS variables. Stencil fill on
  a corner disk is possible but more work than duplicating this URL per theme. */
  --corner-theta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 28'%3E%3Ctext x='14' y='14' font-family='Georgia%2Cserif' font-size='14' font-weight='bold' text-anchor='middle' dominant-baseline='central' fill='%23e6bf95'%3E%CE%98%3C/text%3E%3C/svg%3E");

  color-scheme: light;
}

:root[data-theme="dark"] {
  --color-bg: oklch(0.182 0.021 45.35);
  --color-ink: oklch(0.823 0.074 65.815);
  --color-ink-muted: oklch(0.698 0.089 61.529);
  --color-ink-faint-a: 0.21;
  --color-ink-wall-mix: 16%;
  --color-ink-overlay: oklch(0 0 0 / 0.68);
  --color-ink-border-strong-a: 0.38;
  --color-primary-hover: oklch(0.882 0.054 67.031);
  --shadow-soft: 0 12px 40px oklch(0 0 0 / 0.35);
  --carousel-arrow-border: oklch(0.823 0.074 65.815 / 0.38);
  --carousel-arrow-bg: oklch(0.182 0.021 45.35 / 0.94);
  --carousel-arrow-color: oklch(0.823 0.074 65.815);
  --carousel-arrow-shadow:
    0 0 0 2px oklch(0.182 0.021 45.35 / 0.76), 0 4px 12px oklch(0 0 0 / 0.46),
    0 14px 34px oklch(0 0 0 / 0.75);
  --carousel-arrow-hover-bg: oklch(0.324 0.053 46.184 / 0.95);
  --carousel-arrow-hover-border: oklch(0.868 0.062 64.461 / 0.66);
  --carousel-arrow-hover-shadow:
    0 0 0 2px oklch(0.182 0.021 45.35 / 0.85), 0 6px 14px oklch(0 0 0 / 0.55),
    0 18px 38px oklch(0 0 0 / 0.81);
  --carousel-arrow-focus-outline: oklch(0.823 0.074 65.815);
  --color-selection-bg-a: 0.3;
  --color-selection-fg: var(--color-ink);

  /* Corner theta (dark): fill #1a0f0a (--color-bg): oklch(0.182 0.021 45.35). */
  --corner-theta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 28'%3E%3Ctext x='14' y='14' font-family='Georgia%2Cserif' font-size='14' font-weight='bold' text-anchor='middle' dominant-baseline='central' fill='%231a0f0a'%3E%CE%98%3C/text%3E%3C/svg%3E");

  color-scheme: dark;
}

/* --- Base --- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
::selection {
  background-color: var(--color-selection-bg);
  color: var(--color-selection-fg);
}
::-moz-selection {
  background-color: var(--color-selection-bg);
  color: var(--color-selection-fg);
}

html {
  height: 100%;
  /* Standard properties only: they style overlay scrollbars on Chromium without
     forcing a classic gutter. Don't set ::-webkit-scrollbar width/height; that
     switches Chromium to classic scrollbars as opposed to overlay. On some
     platforms, Chromium may show a classic scrollbar anyway. To deal with this,
     we position the menu button with vw rather than %. */
  scrollbar-color: var(--color-ink-muted) var(--color-bg);
  scrollbar-width: thin;
}

body {
  margin: 0;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1.25rem;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-weight: 700;
  -webkit-font-smoothing: antialiased;
}

/* Position the maze canvas so that its boundary walls are off the screen. */
.maze {
  position: fixed;
  top: calc(-1 * var(--tile-size));
  left: calc(-1 * var(--tile-size));
  /* We use vw and vh so that maze width doesn't change whenever a
  scrollbar appears or disappears; otherwise the maze would shrink or stretch. */
  width: calc(100vw + 2 * var(--tile-size));
  height: calc(100vh + 2 * var(--tile-size));
  pointer-events: none;
  z-index: var(--z-maze);
}
