/* Shared chrome. Loaded by every page, after the page's own <style> block, so these
   rules settle the handful of things that must look identical everywhere: the theme
   button now sits inside the nav pill rather than floating in a different corner on
   each page, and the overflow menu opens the same way. */

.nav-links .nav-theme-btn {
  background: transparent;
  border: 1px solid var(--nav-more-border, rgba(128, 128, 128, .35));
  color: var(--nav-link, inherit);
  border-radius: 999px;
  width: 34px;
  height: 34px;
  line-height: 1;
  font-size: 15px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin-left: 4px;
  flex: none;
  transition: color .2s, border-color .2s, background .2s;
}
.nav-links .nav-theme-btn:hover {
  color: var(--nav-link-active, inherit);
  border-color: var(--nav-more-border-h, var(--nav-dot-hover, currentColor));
  background: var(--nav-more-bg-h, transparent);
}

/* a page that positioned its own toggle absolutely must not also reserve that corner */
body > .theme-toggle-btn,
.ui-container > .theme-toggle-btn,
.glass-card > .theme-toggle-btn { display: none !important; }


/* the nav is fixed; give short pages room so content never starts underneath it */
body { padding-top: 0; }

/* Each page had its own .top-bar padding, so the nav pill sat a few pixels higher or
   lower depending where you were. One rule, applied everywhere, ends the drift. */
#site-nav.top-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 18px 0;
  z-index: 100;
  pointer-events: none;            /* the bar is a rail; only the pill is clickable */
}
#site-nav .nav-links { pointer-events: auto; }

/* The pill itself, so it is the same object on every page — including pages like
   /curriculum that never had nav CSS of their own. Colours still come from each page's
   variables where they exist, with a neutral fallback where they do not. */
#site-nav .nav-links {
  display: flex;
  gap: 26px;
  align-items: center;
  padding: 11px 30px;
  border-radius: 50px;
  background: var(--nav-bg, rgba(20, 20, 24, .55));
  border: 1px solid var(--nav-border, rgba(140, 140, 160, .18));
  box-shadow: var(--nav-shadow, 0 4px 24px rgba(0, 0, 0, .25));
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  margin: 0 auto;
  font-family: 'Times New Roman', Times, serif;
}
#site-nav .nav-link {
  font-size: 21px;
  /* explicit, not 1: font metrics differ between pages that load a serif face and pages
     that do not, and that alone made the pill four pixels shorter on /curriculum */
  line-height: 40px;
  font-weight: 400;
  text-decoration: none;
  color: var(--nav-link, #9aa1ad);
  transition: color .2s;
  white-space: nowrap;
}
#site-nav .nav-link:hover,
#site-nav .nav-link.active { color: var(--nav-link-active, #f0f2f6); }

/* ---------------------------------------------------------------- nav layout
   Nine destinations, all of them visible. They used to be split across the pill and a
   "..." menu, which meant the nav you saw depended on which page you were on and how
   wide the window was. One set, one order, everywhere. */
#site-nav .nav-set {
  display: flex;
  align-items: center;
  gap: 20px;
}
#site-nav .nav-link { font-size: 19px; }

/* The theme button gets its own zone at the end of the pill, behind a hairline. */
#site-nav .nav-div {
  width: 1px;
  height: 20px;
  background: var(--nav-border, rgba(140, 140, 160, .3));
  margin: 0 14px 0 18px;
  flex: none;
}
#site-nav .nav-links { gap: 0; padding: 9px 22px 9px 30px; }
.nav-links .nav-theme-btn { margin-left: 0; width: 32px; height: 32px; font-size: 14px; }

/* the burger only exists below the breakpoint */
#site-nav .nav-burger { display: none; }

@media (max-width: 1040px) {
  #site-nav .nav-burger {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 34px; height: 34px;
    padding: 0 9px;
    background: transparent;
    border: 1px solid var(--nav-more-border, rgba(128, 128, 128, .35));
    border-radius: 999px;
    cursor: pointer;
    flex: none;
  }
  #site-nav .nav-burger span {
    display: block;
    height: 1.5px;
    background: var(--nav-link, #9aa1ad);
    border-radius: 2px;
  }
  /* the same nine links, stacked, so nothing is unreachable on a phone */
  #site-nav .nav-set {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 190px;
    padding: 10px 0;
    border-radius: 16px;
    background: var(--nav-menu-bg, #101014);
    border: 1px solid var(--nav-border, rgba(140, 140, 160, .18));
    box-shadow: 0 12px 40px rgba(0, 0, 0, .4);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }
  #site-nav .nav-set.open { display: flex; }
  #site-nav .nav-set .nav-link {
    width: 100%;
    padding: 8px 22px;
    line-height: 1.5;
    box-sizing: border-box;
  }
  #site-nav .nav-links { position: relative; gap: 0; padding: 9px 14px; }
  #site-nav .nav-div { margin: 0 10px; }
}

/* The dropdown sits over body copy, so it is opaque rather than tinted — at 96% the
   headline underneath still read through it. */
@media (max-width: 1040px) {
  html[data-theme="light"] #site-nav .nav-set,
  body.light-mode #site-nav .nav-set {
    background: var(--nav-menu-bg, #ffffff);
    border-color: rgba(0, 0, 0, .12);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .18);
  }
}

/* ---------------------------------------------------------------- leave a note
   Injected by chrome.js on every page except the guestbook itself and the studio. Ten
   pages used to carry their own copy of the anchor and two had none at all. Pages that
   define the --guest-* tokens keep their own colours; the fallbacks cover the pages that
   never had this button before (home, curriculum). */
.guestbook-float {
  position: fixed;
  bottom: 28px;
  right: 32px;
  z-index: 200;
  font-family: 'Times New Roman', Times, serif;
  font-size: 13px;
  font-style: italic;
  color: var(--guest-color, rgba(255, 255, 255, .58));
  text-decoration: none;
  letter-spacing: .06em;
  padding: 10px 18px;
  border: 1px solid var(--guest-border, rgba(255, 255, 255, .26));
  border-radius: 4px;
  background: var(--guest-bg, rgba(22, 22, 22, .82));
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: color .3s, border-color .3s, background .25s;
  line-height: 1;
}
.guestbook-float:hover {
  color: var(--guest-color-h, rgba(255, 255, 255, .9));
  border-color: var(--guest-border-h, rgba(255, 255, 255, .52));
}
.guestbook-float span { opacity: .7; margin-right: 3px; }

/* private sections appear only after the session is confirmed, so they must not flash */
.nav-link.nav-private { animation: navFade .18s ease-out; }
@keyframes navFade { from { opacity: 0; } to { opacity: 1; } }

/* ---------------------------------------------------------------- admin bar
   Appears only for a signed-in session, and never inside the studio. It sits
   bottom-left so it clears the "leave a note" button on the right, and it stays out
   of the nav — which is public, fixed, and the same for every visitor. */
#admin-bar {
  position: fixed;
  bottom: 24px;
  left: 26px;
  z-index: 210;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px 6px 5px 5px;
  border-radius: 999px;
  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 12.5px;
  background: rgba(10, 12, 20, .82);
  border: 1px solid rgba(150, 175, 220, .26);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .5);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
#admin-bar a, #admin-bar button {
  font: inherit;
  color: rgba(226, 233, 248, .72);
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 6px 12px;
  border-radius: 999px;
  white-space: nowrap;
  transition: background .18s, color .18s;
}
#admin-bar a:hover, #admin-bar button:hover {
  background: rgba(122, 162, 247, .18);
  color: #fff;
}
#admin-bar .ab-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: #dce6ff;
  background: rgba(122, 162, 247, .16);
}
#admin-bar .ab-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: #6ec48a;
  box-shadow: 0 0 6px rgba(110, 196, 138, .9);
  flex: none;
}
#admin-bar .ab-out { color: rgba(226, 233, 248, .45); }
#admin-bar .ab-out:hover { background: rgba(224, 108, 117, .18); color: #ffd9dc; }

@media (max-width: 720px) {
  /* A compact pill in the corner. It used to stretch the full width of the phone,
     which left a 366px empty bar sitting across the bottom of every page. */
  #admin-bar { left: 12px; right: auto; bottom: 12px; }
}

/* the notebook row inside the admin bar */
#admin-bar .ab-sep {
  width: 1px;
  height: 16px;
  background: rgba(150, 175, 220, .24);
  flex: none;
  margin: 0 3px;
}
#admin-bar .ab-act.on {
  background: rgba(122, 162, 247, .2);
  color: #fff;
}

/* ---------------------------------------------------------------- admin bar, at rest
   Wide and pinned to the bottom-left, the bar crossed the reading column and covered
   text. It shows only the Studio pill until pointed at or focused. */
#admin-bar .ab-act,
#admin-bar .ab-sep {
  max-width: 0;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  transition: max-width .22s ease, opacity .18s ease,
              padding .22s ease, margin .22s ease;
}
#admin-bar:hover .ab-act,
#admin-bar:focus-within .ab-act {
  max-width: 160px;
  padding-left: 12px;
  padding-right: 12px;
  opacity: 1;
}
#admin-bar:hover .ab-sep,
#admin-bar:focus-within .ab-sep {
  max-width: 1px;
  margin-left: 3px;
  margin-right: 3px;
  opacity: 1;
}
/* the hit area stays generous even while collapsed */
#admin-bar { padding-right: 10px; }

/* On a touch screen there is no hover, so it opens on a tap instead — left open it
   wrapped to two lines across the bottom of a phone and covered the writing. */
@media (hover: none) {
  #admin-bar.open .ab-act {
    max-width: 160px; padding-left: 12px; padding-right: 12px; opacity: 1;
  }
  #admin-bar.open .ab-sep { max-width: 1px; margin-left: 3px; margin-right: 3px; opacity: 1; }
  #admin-bar.open { flex-wrap: wrap; max-width: calc(100vw - 24px); }
  #admin-bar .ab-brand { padding: 9px 14px; }     /* a comfortable thumb target */
}

/* Room under the last thing on the page. Two controls float above the bottom edge on
   every page — leave-a-note on the right, the studio pill on the left — and on a phone
   there is no margin for them to sit in, so they landed on the final paragraph. */
@media (max-width: 820px) {
  body { padding-bottom: 84px; }
  .guestbook-float { bottom: 14px; right: 14px; font-size: 12px; padding: 9px 14px; }
}

/* ===========================================================================
   Phones.

   These pages were laid out for a desktop with two fixed side-rails pinned at
   absolute coordinates — the category chips at (120, 100) and the calendar at
   (50, 510) — while the content was pushed clear of them with a hard
   margin-left of 390–430px. On a 390px screen that puts the entire list off
   the right-hand edge and drops the rails on top of the writing. The books
   page rendered as a blank screen with two stray arrows on it.

   The rails are inline styles, so unsetting them needs !important. Everything
   the site genuinely wants pinned — the nav, the leave-a-note button, the
   admin bar, the photo viewer — is excluded by id or class.
   =========================================================================== */
@media (max-width: 820px) {

  /* 1. the side-rails rejoin the document */
  .glass-card [style*="position: fixed"]:not(#site-nav):not(.guestbook-float):not(#admin-bar):not(#viewer):not(#calendarTooltip):not(#admin-gate) {
    position: static !important;
    top: auto !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    width: auto !important;
    max-width: 100% !important;
    margin: 0 auto 28px !important;
    z-index: auto !important;
  }

  /* 2. the content stops making room for rails that are no longer beside it */
  .entry-list,
  #entryList,
  #sortedWordList,
  .page-layout > div[style*="margin-left"] {
    margin-left: 0 !important;
    max-width: 100% !important;
  }

  /* 3. nothing runs into the edge of the screen */
  .page-layout,
  .about-card-inner,
  .page-wrap {
    padding-left: 18px !important;
    padding-right: 18px !important;
    max-width: 100% !important;
  }

  /* 4. type that was sized for a wide column */
  #profile-bio-text { font-size: 17px !important; line-height: 1.6 !important; }
  .about-card-inner { font-size: 18px !important; }
  .page-intro-heading { font-size: 1.7rem !important; }
  .page-intro-desc { font-size: 1rem !important; }
  .tutorial-title { font-size: 1.9rem !important; }
  .entry-item h2 { font-size: 1.3rem !important; }
  .chip { font-size: 16px !important; margin-right: 14px !important; }

  /* 5. rows that were built as wide flex bars stack instead */
  .entry-item {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 10px !important;
  }
  .entry-item .entry-date {
    width: auto !important;
    text-align: left !important;
    padding-right: 0 !important;
    border-right: 0 !important;
  }
  .entry-item > div[style*="padding-left"] { padding-left: 0 !important; }

  /* 6. the activity calendar is a fixed 7-column grid; give it the full width */
  #activityCalendar {
    max-width: 100% !important;
    padding-left: 0 !important;
    justify-items: center;
  }

  /* 7. the nav pill must not be wider than the phone */
  #site-nav .nav-links { max-width: calc(100vw - 24px); }

  /* 8. media never overflows its card */
  img, video, canvas, iframe { max-width: 100%; }
}

/* Tap targets on a touch screen: a 25px serif link is a 25px serif link, but the
   row it sits in can be tall enough to hit. */
@media (hover: none) and (max-width: 820px) {
  #site-nav .nav-set .nav-link { padding: 10px 22px !important; }
  .proj-links a, .post-link, .lesson { min-height: 44px; }
}

/* ---------------------------------------------------------------------------- the sky
   Two backgrounds, one rule set.

   #starfield is the ordinary one: a 2D canvas chrome.js paints once per page, stars on
   black. #cosmic-canvas is the landing page's black hole, which is WebGL and runs a
   frame loop — it lives on /about and nowhere else, which is why the pages you read
   stayed quick after the animation came out of them.

   Both sit behind everything and ignore the mouse. The ground colour is on the canvas
   itself rather than on each page's body, so a page gets space by loading chrome.js and
   needs no CSS of its own. */
#starfield,
#cosmic-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Behind the text, in front of the page's own background colour. z-index:0 would
     paint *above* any content that isn't itself positioned — a positioned box at 0
     comes after in-flow text in the painting order — and would hide half the site. */
  z-index: -1;
  pointer-events: none;
  display: block;
}

#starfield {
  background: #05060a;
  /* Fade in rather than appear: the canvas paints a frame or two after the text, and a
     sudden field of stars behind a paragraph you are already reading is a flinch. */
  animation: sky-in 900ms ease-out both;
}

#cosmic-canvas {
  background: #000;
  /* Dimmed, because the disk at full strength is brighter than the text in front of it.
     brightness() rather than opacity: opacity would mix it with the page's ground and
     grey the black out, while this darkens the image and leaves black as black. */
  filter: brightness(0.3);
}

@keyframes sky-in { from { opacity: 0; } to { opacity: 1; } }

/* Light mode has its own pale ground; stars on it would be invisible smudges. */
html[data-theme="light"] #starfield { display: none; }

@media (prefers-reduced-motion: reduce) {
  #starfield { animation: none; }
}


/* ------------------------------------------------------------------- film grain
   Six pages still carry <div class="grain">, and when the animation came out the rule
   that made it do anything went with it. It is the reason the black hole read as
   footage rather than as a demo: a still image of a night sky is too clean, and a very
   fine noise over the top is what a camera would have put there. 4% opacity, a 256px
   tile of fractal noise, no animation — it costs one composited layer. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 256px;
}

/* Grain belongs to the dark. On a pale ground it is dirt on the screen. */
html[data-theme="light"] .grain { display: none; }

/* ---------------------------------------------------------------------- vignette
   The other half of the look: a lens darkens its corners, and without that the frame
   has no edge and the disk floats in a rectangle. Only on the page with the black
   hole — on a page of writing it would just be a dark border. Sits above the canvas
   and below the text, which is at z-index 20. */
html[data-sky="hole"] body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(ellipse 78% 68% at 50% 50%,
              rgba(0,0,0,0) 42%, rgba(0,0,0,.34) 76%, rgba(0,0,0,.62) 100%);
}
