/* ═══════════════════════════════════════════════════════════════════════════
   CHROME — tokens, base, and the fixed top bar. Shared by the landing page and
   the archive so the palette and the header live in exactly one place.
   Typefaces come from type.css, which loads first.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* ink & ground */
  --ground:      #F9F9FB;   /* the page */
  --bar-ground:  #FFFFFF;   /* the nav bar alone sits a shade brighter */
  --ink:         #202020;   /* 15.5:1 on --ground */
  --ink-quiet:   #6E6E6E;   /* 4.9:1 — labels and hover only, never body */
  --media-ground:#F0F0F0;   /* behind an image while it loads */
  --on-ink:      #FFFFFF;

  /* layout */
  --fs:  13px;
  --lh:  1.18;
  --gut: 10px;              /* the whole site sits on a 10px margin */
  --bar: 34px;              /* header height */
  --nav-reserve: 315px;     /* what the nav measures, plus a gutter — the bar
                               title clamps itself off this so it never runs
                               into the links. Measured, not guessed: the nav
                               is the same five items on every page. 288px of
                               them since "++ Work" became "More work", which
                               is why this is 315 and not 300. */

  /* motion */
  --ease-out-quart: cubic-bezier(.25, 1, .5, 1);
  --ease-out-quint: cubic-bezier(.22, 1, .36, 1);

  /* z-scale */
  --z-reel:    1;
  --z-caption: 2;
  --z-header:  10;
}

/* ─── Dark ────────────────────────────────────────────────────────────────────
   Light is the default; dark is opt-in and remembered. Only the tokens change,
   so every page that draws from them follows without its own dark rules. */

:root[data-theme="dark"]{
  --ground:      #18191B;
  --bar-ground:  #202124;   /* a shade lighter than the page, as white is in light */
  --ink:         #EDEDED;   /* 15.0:1 on the dark ground */
  --ink-quiet:   #8A8C90;   /* 5.1:1 — still safe for labels */
  --media-ground:#232427;
  --on-ink:      #18191B;
}

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

body{
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-size: var(--fs);
  line-height: var(--lh);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

a{ color: inherit; text-decoration: none; }

:focus-visible{
  outline: 1px solid var(--ink);
  outline-offset: 2px;
}

.sr-only{
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ─── Theme toggle ────────────────────────────────────────────────────────────
   Outline only. A pill, a sun and a moon, and a ring that slides to whichever
   side is live. Nothing is filled.

   It is the last item in the nav, so it has to live inside the 34px bar: at
   10px of padding a 22px pill leaves 2px, where the old free-standing 26px one
   would have pushed 2px out through the bottom. */

.themer{
  /* every position below is derived from these four, so the knob stays centred
     on its icon whatever the pill is resized to */
  --t-w:    48px;
  --t-h:    22px;
  --t-pad:   4px;
  --t-icon: 12px;
  --t-knob: calc(var(--t-h) - 6px);

  appearance: none;
  -webkit-appearance: none;
  background: none;
  padding: 0 var(--t-pad);
  font: inherit;
  cursor: pointer;

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;   /* the icons sit at the two ends — without
                                       this they pack left and the knob lands
                                       8px right of the moon */
  width: var(--t-w);
  height: var(--t-h);
  border: 1px solid var(--ink);
  border-radius: 999px;
  color: var(--ink);
}

.themer svg{
  width: var(--t-icon);
  height: var(--t-icon);
  flex: 0 0 var(--t-icon);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .35;

  /* The knob is absolutely positioned, so it paints above these static flex
     items — filling it would hide whichever icon it lands on. Positioning the
     icons puts them back on top of it. */
  position: relative;
  z-index: 1;

  transition: opacity .22s var(--ease-out-quart),
              color .22s var(--ease-out-quart);
}

/* The live side sits on the filled knob, so it reverses out of it: --on-ink is
   white against the light theme's ink and near-black against the dark theme's,
   which is what makes the state read at a glance rather than being carried by
   a 1px ring alone. */
:root:not([data-theme="dark"]) .themer .themer__sun,
:root[data-theme="dark"] .themer .themer__moon{
  opacity: 1;
  color: var(--on-ink);
}

/* the knob that marks the live side — filled, centred on the sun to start */
.themer__knob{
  position: absolute;
  top: 50%;
  left: calc(var(--t-pad) + var(--t-icon) / 2 - var(--t-knob) / 2);
  width: var(--t-knob);
  height: var(--t-knob);
  margin-top: calc(var(--t-knob) / -2);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 50%;
  transition: transform .28s var(--ease-out-quart);
}

/* exactly the distance between the two icon centres */
:root[data-theme="dark"] .themer__knob{
  transform: translateX(calc(var(--t-w) - 2px - var(--t-pad) * 2 - var(--t-icon)));
}

@media (prefers-reduced-motion: reduce){
  .themer svg, .themer__knob{ transition: none; }
}


/* ─── Top bar ─────────────────────────────────────────────────────────────── */

.bar{
  position: fixed; inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--bar);
  padding: var(--gut);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gut);
  background: var(--bar-ground);
  animation: chrome-fade .5s var(--ease-out-quart) both;

  /* js/bar.js hands the screen over to the images on the way down and gives it
     back on the way up. Transform rather than top, so it composites and never
     touches layout — and -100% is measured off the bar's own height, which is
     the one number that is already right at every width, including the taller
     wrapped bar on a phone. */
  transition: transform .38s var(--ease-out-quart);
  will-change: transform;
}
.bar--away{ transform: translateY(-100%); }

/* A compact uppercase lockup — matching that weight and case is what makes the
   corner read like the reference's. */
.wordmark{
  font-weight: 650;             /* the top of the subset's 400-650 axis */
  text-transform: uppercase;
  letter-spacing: normal;
  white-space: nowrap;
}

/* Project pages put the piece's name in the bar, aligned to the left edge of
   their image column (a third across) rather than centred — as the reference
   does. Absolute so it never competes with the wordmark or the nav for space. */
.bar__title{
  font-size: calc(var(--fs) + 1px);
  position: absolute;
  left: calc(var(--gut) + (100% - var(--gut) * 2) / 3);
  top: var(--gut);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;

  /* A third is what the title is allowed, but a third is not always what is
     free: the nav is content-sized and costs the same ~273px at every width, so
     from about 880px down a third of the bar reaches into it — the long titles
     (Thuma's, TEDxRISD's) were landing on top of "++ Work". Whichever is
     smaller wins, so the title truncates instead of colliding. Above 880 the
     first term governs and nothing about the wide bar changes. */
  max-width: min(calc((100% - var(--gut) * 2) / 3),
                 calc(66.6667% - var(--nav-reserve)));
}

.nav{
  font-size: calc(var(--fs) + 1px);
  display: flex;
  align-items: flex-start;      /* the links keep the wordmark's top edge; the
                                   toggle pulls itself up to sit level with
                                   their text rather than dragging them down */
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Optically centred on the link text: the pill is 22px against a 16.5px line
   box, so it rises by half the difference. */
.nav .themer{
  margin-top: -3px;
  margin-left: 3px;
  flex: 0 0 auto;
}

.nav a{
  padding: 0 6px;
  border-radius: 999px;
  white-space: nowrap;
  transition: color .18s var(--ease-out-quart),
              background-color .18s var(--ease-out-quart);
}
.nav a:hover{ color: var(--ink-quiet); }

/* The current page wears the pill — as Backstage does on the reference. The
   landing page marks the wordmark instead, since it dropped its own nav item. */
.nav a[aria-current="page"]{
  background: var(--ink);
  color: var(--on-ink);
}
.nav a[aria-current="page"]:hover{ color: var(--on-ink); }

@keyframes chrome-fade{ from { opacity: 0 } }

@media (max-width: 639px){
  /* The toggle has no text baseline, so under the bar's baseline alignment it
     sets the line box's depth: the bar measures 39px here. --bar has to say so,
     or content keyed off it starts 5px under the bar. */
  :root{ --bar: 40px; }

  /* height:auto is the safety net for narrow phones, where the nav wraps to a
     second row; --bar grows to match so anything keyed off it moves down too. */
  .bar{ height: auto; min-height: var(--bar); align-items: baseline; }
  .nav{ gap: 2px 4px; }
  .nav a{ padding: 0 4px; }
  .wordmark{ letter-spacing: normal; }
  .bar__title{ display: none; }   /* no room beside the wordmark and nav */
}

@media (max-width: 360px){
  /* the nav drops below the wordmark here; 58px is what the two rows plus the
     toggle actually measure */
  :root{ --bar: 58px; }
}

@media (prefers-reduced-motion: reduce){
  .bar{ animation-duration: .01ms !important; transition: none; }
  /* the script bows out here too, so this is only a belt-and-braces reset */
  .bar--away{ transform: none; }
}
