/* Comic Neue, the open-source cut of Comic Sans. See the --font-display note
 * below for why the real Comic Sans cannot be named on its own. Loaded here
 * rather than as a <link> in twelve page heads so the font is one edit. */
@import url("https://fonts.googleapis.com/css2?family=Comic+Neue:ital,wght@0,400;0,700;1,400&display=swap");

/* iansolberg.us design tokens, settled with Ian 2026-08-27,
 * REPALETTED to lilac and Comic Neue 2026-09-13.
 *
 * Load this FIRST, before any other stylesheet.
 * The decision record, including every direction that was rejected, lives in
 * Ian's memory bank at memory/brand.md and memory/personal-website.md.
 *
 * Every colour pair below clears WCAG AA against --page, in BOTH themes. Do not
 * darken a page or dim any text without recomputing: in dark the small
 * monospace metadata fails first (it already had to be lifted from 4.26:1 to
 * 4.50:1), and in light it is the accent.
 */

/* Dark is the default, per the 2026-08-13 contract. Light was added
 * 2026-08-27 at Ian's request ("kinda want light/dark option somewhere").
 *
 * Three ways in, in priority order: an explicit [data-theme] on <html> wins,
 * then the OS preference, then dark. So the toggle is a one-attribute flip and
 * a visitor with no stated preference still gets the design as approved.
 */
:root, [data-theme="dark"] {
  /* Surface and ink. Near-black with a VIOLET cast, not the previous warm one:
   * lilac sitting on a warm brown-black reads muddy, and the whole point of the
   * palette is that the accent looks intentional. */
  --page:      #121018;
  --heading:   #f5f2fa;  /* 17.04:1 */
  --body:      #b0a8c2;  /*  8.29:1 */
  --meta:      #8b839c;  /*  5.23:1, the tightest in the set */
  --kicker:    #948ca6;  /*  5.89:1 */
  --rule:      #27232f;

  /* LILAC IS THE BRAND (Ian, 2026-09-13: "a softer purple / lilac colour
   * scheme"). This SUPERSEDES the orange #ff7a1a settled 2026-08-27, which is
   * dead everywhere including memory/brand.md. On dark it works everywhere,
   * exactly as the orange did. */
  --brand:     #c4a7f5;  /* the identity colour, unchanged in both themes */
  --accent:    #c4a7f5;  /*  9.16:1 on dark, safe as text here */
  --on-brand:  #121018;  /*  9.16:1 against a --brand fill */
}

/* Light: cool paper with the same violet cast, mirroring the dark rather than
 * going sterile white. */
[data-theme="light"] {
  --page:      #faf7fb;
  --heading:   #171320;  /* 17.18:1 */
  --body:      #4b4358;  /*  8.81:1 */
  --meta:      #6d6479;  /*  5.27:1 */
  --kicker:    #6d6479;  /*  5.27:1 */
  --rule:      #e2dae9;

  /* THE BRAND LILAC IS UNCHANGED, but it CANNOT be text on paper: #c4a7f5 is
   * 1.94:1 there, which is the same trap the orange had at 2.42:1. A lilac
   * light enough to read as lilac can never clear 4.5:1 on paper. So on light
   * it is a FILL and --accent is a darkened same-hue variant for text and
   * links. Reusing the dark accent on paper is the single most common
   * light-mode bug; this is what avoiding it costs. */
  --brand:     #c4a7f5;  /* fills, illustration, large shapes only */
  --accent:    #6d28c4;  /*  7.18:1, text and links */
  --on-brand:  #171320;  /*  8.86:1 against a --brand fill */
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --page:      #faf7fb;
    --heading:   #171320;
    --body:      #4b4358;
    --meta:      #6d6479;
    --kicker:    #6d6479;
    --rule:      #e8e0ee;
    --brand:     #c4a7f5;
    --accent:    #6d28c4;
    --on-brand:  #171320;
  }
}

:root {
  /* Type. COMIC NEUE for display and body (Ian, 2026-09-13: he likes Comic Sans
   * and has weighed the professionalism question himself). This SUPERSEDES the
   * serif stacks settled 2026-08-13.
   *
   * WHY COMIC NEUE AND NOT "Comic Sans MS": Comic Sans is a SYSTEM font. It
   * ships with Windows and macOS and is absent from most Linux and Android
   * installs, so naming it alone silently serves a fallback to a large slice of
   * visitors and the author never sees it. Comic Neue is the open-source cut of
   * the same shape, loaded as a webfont, so every visitor gets the same page.
   * Comic Sans MS stays in the stack AFTER it: anyone who has the real thing
   * locally renders before the webfont arrives, which removes the flash.
   *
   * The mono stack is unchanged and still metadata-only. */
  --font-display: "Comic Neue", "Comic Sans MS", "Chalkboard SE", cursive;
  --font-body:    "Comic Neue", "Comic Sans MS", "Chalkboard SE", cursive;
  --font-mono:    ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Headline metrics measured on a 390px phone frame, which is the width the
   * design was approved at.
   *
   * RETUNED FOR COMIC NEUE 2026-09-13. The old values were measured against
   * Georgia and carried straight over, which is what made the spacing read
   * uneven: this face has a much larger x-height and wider default sidebearings,
   * so -0.02em tracking closed the counters up while a 1.16 leading left the
   * tall ascenders crowding the line above. Tracking is now near-neutral and
   * the leading is looser; the measure widens because the same character count
   * occupies more room in this face. */
  --headline-size:    1.95rem;
  --headline-leading: 1.28;
  --headline-tracking: -0.005em;
  --measure:          28ch;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--body);
  font-family: var(--font-body);
  /* 1.55, down from the 1.62 tuned for Georgia: Comic Neue's larger x-height
   * fills more of the line box, so the same number reads airier. */
  line-height: 1.55;
}

/* The masthead: portrait beside the name, role line beneath.
 * Untreated photograph, always. No filter, tint, or blend on this image.
 *
 * SQUARE OR PORTRAIT ONLY, NEVER A CIRCLE (Ian, 2026-08-27: "I don't want a
 * circle I want a square or portrait shape only"). This supersedes the
 * "small circle" in the 2026-08-27 brand order, which shipped
 * border-radius: 50% here. 4:5 is the byline shape; the corner radius is
 * small enough to read as a rectangle rather than rounding the silhouette.
 * Do not reintroduce a round or pill radius on this image. */
.masthead { display: flex; align-items: center; gap: 18px; }
/* 104x130, up from 62x78 (Ian, 2026-09-13: "make my photo larger please").
 * Still 4:5, and still well inside the source file's 320x400, so it scales up
 * without softening. The corner radius does NOT grow with it: assertion 1b
 * fails a round or pill silhouette, which is the thing he ruled out. */
.masthead img {
  width: 104px; height: 130px; flex: 0 0 104px;
  border-radius: 4px; object-fit: cover;
  border: 1px solid var(--rule);
}
.masthead .name {
  font-family: var(--font-display); font-weight: 400;
  font-size: 1.28rem; line-height: 1.15; letter-spacing: -0.015em;
  color: var(--heading);
}
/* Comic Neue here too, not the mono (Ian, 2026-09-13).
 *
 * NO LONGER UPPERCASE. It became three stacked lines matching his GitHub
 * profile, written in title case, and three lines of letterspaced caps at this
 * size shouts where one line merely labelled. Tracking goes to near-neutral for
 * the same reason: it existed to open up uppercase. */
.masthead .role {
  font-family: var(--font-display); font-size: 0.82rem; font-weight: 400;
  letter-spacing: 0.005em;
  color: var(--kicker); margin-top: 3px;
}
.masthead .role:first-of-type { margin-top: 7px; }

/* The tagline IS the headline. There is no separate tagline line: that was the
 * specific change that made this version work. */
.headline {
  font-family: var(--font-display); font-weight: 400;
  font-size: var(--headline-size);
  line-height: var(--headline-leading);
  letter-spacing: var(--headline-tracking);
  color: var(--heading);
  max-width: var(--measure);
  margin: 0;
}
.headline em { font-style: italic; color: var(--accent); }

/* Kickers, dates and counts. THESE ARE COMIC NEUE NOW (Ian, 2026-09-13: "more
 * comic sans please - the little bubbles and descriptions etc"), which
 * supersedes the 2026-08-13 monospace-for-metadata rule. Sizes are up and
 * tracking is down from the monospace settings for the reason in .masthead
 * .role above: this face is wider, so the old values left visible gaps. */
.kicker {
  font-family: var(--font-display); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--kicker);
}
.meta {
  font-family: var(--font-display); font-size: 0.78rem;
  color: var(--meta);
}

.rule { border: 0; border-top: 1px solid var(--rule); }

/* 700 not 400: Comic Neue's regular weight is noticeably lighter than Georgia's
 * and headings stopped separating from body copy at the same size. Tracking is
 * neutral for the reason in the headline metrics above. */
h1, h2, h3, h4 {
  font-family: var(--font-display); font-weight: 700;
  color: var(--heading); letter-spacing: 0;
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* A brand fill: the one place the full-strength orange appears as a surface.
 * Text on it uses --on-brand, never --heading, because the ink has to flip with
 * the theme's fill contrast rather than with the page. */
.brand-fill {
  background: var(--brand);
  color: var(--on-brand);
  border-radius: 6px;
  padding: 12px 15px;
}

/* Botanical decoration. The motifs are drawn with stroke="currentColor", so they
 * inherit whatever colour the container sets and one file serves both themes. They are DECORATION: never the only carrier of
 * meaning, always low opacity so they sit behind the reading, and never placed
 * where they reduce text contrast. */
.deco { color: var(--brand); opacity: 0.16; pointer-events: none; }
.deco--mark { opacity: 0.55; }   /* a small motif used as a section mark */
.deco--foot { opacity: 0.40; }

/* Sentence case everywhere, per the 2026-08-13 contract. Enforced by writing,
 * not by CSS: never add text-transform beyond the monospace metadata above. */
