/* The Pre-AI/Post-AI toggle and the wipe that plays between them.
 *
 * Loaded by BOTH designs, which is why nothing here relies on standards mode:
 * index.html has no doctype on purpose (css/style.css carries 90+ unitless
 * declarations that only work in quirks mode), so every NONZERO length below
 * carries an explicit unit and no rule depends on the standards box model.
 * That distinction is the whole hazard: `padding-left: 275` is a length quirks
 * mode reads as pixels and standards mode discards. The six bare numbers here
 * are z-index, font-weight, line-height and two zeroes -- unitless by
 * specification or by preference, and identical in both modes.
 *
 * It is a separate file rather than an addition to either stylesheet because
 * css/style.css is frozen -- quirks-mode-only and not to be edited -- and
 * css/post-ai.css belongs to one design while this belongs to both. */

/* --- the toggle ---------------------------------------------------------- */

/* A two-option segmented control shaped exactly like the portrait switcher on
 * the Post-AI hero (Chibi / Brick / Voxel): the version you are on is the
 * raised segment, the other is a link.
 *
 * SQUARE, deliberately. The Post-AI design system sets --r-sm, --r-lg and even
 * --r-pill to 0 -- nothing in it is rounded, and the earlier pill shape was
 * fighting that everywhere it appeared. The classic page cannot read those
 * tokens (different stylesheet, different document), so the geometry is
 * restated here in plain values that hold up in both a quirks-mode and a
 * standards-mode page. */
.mode-switch {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  /* 4px, the radius of the .chinese-name badge immediately to its left. Square
     matched the Post-AI switcher this is modelled on, but on THIS page the
     nearest neighbour is that badge, and matching what sits beside it matters
     more than matching a control on another page. */
  border-radius: 4px;
  background: #ececea;
  border: 1px solid #e0e0dd;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.5;
  vertical-align: middle;
  white-space: nowrap;
}

.mode-switch__current,
a.mode-toggle {
  display: inline-block;
  padding: 5px 14px;
  border-radius: 3px;
  text-decoration: none;
  letter-spacing: 0.01em;
}

/* The segment you are on: white, full ink, and not a link. */
.mode-switch__current {
  color: #1b1b1a;
  background: #ffffff;
}

/* The one you are not on. a.mode-toggle rather than .mode-toggle: an
   element+class selector outranks any bare `a` rule among the four stylesheets
   the classic page loads, whatever order they arrive in. Styled on the class
   alone, something upstream kept colouring this text and it rendered
   unreadable blue-on-dark. */
a.mode-toggle,
a.mode-toggle:visited {
  color: #6a6a63;
  background: transparent;
  transition: color 160ms ease, background 160ms ease;
}

a.mode-toggle:hover,
a.mode-toggle:focus-visible {
  color: #1b1b1a;
  background: rgba(255, 255, 255, 0.66);
  text-decoration: none;
}

/* Flexbox, not a float with a hand-tuned margin.
   A float aligns to the TOP of the line box, so a control shorter than the
   heading always hangs low and the only remedy is a negative margin guessed
   against a screenshot -- which took three passes and was still a few pixels
   out. align-items: center makes the browser do the arithmetic: whatever the
   heading's size or the control's height, their centres line up.
   Flexbox behaves identically in quirks mode; it is the box model that differs
   there, and no width or padding here depends on it. */
.name-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* Nothing here styles the control's box, because neither variant HAS a box.
   These selectors used to: #flex-outer .mode-switch set a blue wash and a
   border for the filled design, at specificity (1,1,0), while the variant's
   own reset sits at (0,1,0) -- so `background: none` never won and the
   underline was being drawn underneath a box that should not have existed.
   The variants own their appearance completely now; anything added back here
   will silently outrank them. */

@media (max-width: 40rem) {
  .name-line { gap: 0.5rem; }
}

/* --- the classic page's switch: two variants, one markup ----------------- */

/* Both variants below drive the SAME DOM:
 *
 *   <span class="mode-switch mode-switch--underline">   <- or --knob
 *     <span class="mode-switch__thumb"></span>
 *     <span class="mode-switch__current">Original</span>
 *     <a class="mode-toggle">AI-built</a>
 *   </span>
 *
 * so choosing between them is one word in index.html and nothing else. The
 * thumb is a real element rather than a background because a background cannot
 * travel between two elements, and travelling is the point of both.
 *
 * Equal-width labels are what make the arithmetic work in either variant:
 * flex: 1 1 0 on both means one label is exactly 50%, so a thumb of that width
 * lands on the other with translateX(100%). Give the labels their natural
 * widths and the thumb stops matching whichever one it sits under. */
.mode-switch--underline,
.mode-switch--knob {
  position: relative;
  gap: 0;
}

.mode-switch--underline .mode-switch__current,
.mode-switch--underline a.mode-toggle,
.mode-switch--knob .mode-switch__current,
.mode-switch--knob a.mode-toggle {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  text-align: center;
  background: none;
  box-shadow: none;
  transition: color 220ms ease;
}

/* --- variant A (active): a sliding underline ----------------------------- */

/* No well, no border, no fill. index.html is headings, prose and links with no
   other boxed control anywhere except the Columbia bar, so every filled version
   of this read as a foreign object however it was tuned.
   The reset has to be complete, and it has to outrank the base rule: the base
   .mode-switch carries a box for the Post-AI nav, which does want one. Same
   specificity, defined later, so this wins -- but an id-scoped rule elsewhere
   would beat both, which is exactly what went wrong before. */
.mode-switch--underline {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  font-size: 14px;
  letter-spacing: 0.01em;
  /* The flex row centres this against the heading's full box, but the name's
     visual mass sits above its baseline, so dead centre reads a touch low.
     `top` on an already-relative element nudges it optically without moving
     anything in layout -- and the thumb, absolutely positioned against this
     box, rides along instead of drifting out of alignment. */
  top: -4px;
}

.mode-switch--underline .mode-switch__current,
.mode-switch--underline a.mode-toggle {
  /* Generous sides so the two words read as a pair rather than a collision,
     and enough below for the rule to sit clear of the descenders. */
  padding: 1px 14px 8px;
}

.mode-switch--underline .mode-switch__thumb {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 50%;
  height: 2px;
  border-radius: 2px;
  background: #1989BF;
  box-shadow: none;
  transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* A hairline under the whole control, so the rule reads as a marker moving
   along a track rather than a stray underline on one word. Very light -- it
   should be felt more than seen. */
.mode-switch--underline::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: rgba(25, 137, 191, 0.18);
}

.mode-switch--underline:hover .mode-switch__thumb,
.mode-switch--underline:focus-within .mode-switch__thumb {
  transform: translateX(100%);
}

/* --- variant B (alternate): a track with a knob -------------------------- */

/* Kept ready as the fallback if the underline reads as too quiet. Switch by
   changing --underline to --knob on the <span> in index.html; nothing else
   moves. `order` puts the thumb BETWEEN the two labels without touching the
   markup, which is what lets one DOM serve both. */
.mode-switch--knob {
  padding: 0;
  background: none;
  border: 0;
  gap: 0.55rem;
  align-items: center;
}

.mode-switch--knob .mode-switch__current { order: 1; flex: 0 0 auto; padding: 0; }
.mode-switch--knob .mode-switch__thumb   { order: 2; flex: 0 0 auto; }
.mode-switch--knob a.mode-toggle         { order: 3; flex: 0 0 auto; padding: 0; }

.mode-switch--knob .mode-switch__thumb {
  position: relative;
  width: 38px;
  height: 21px;
  border-radius: 999px;
  background: rgba(25, 137, 191, 0.16);
  border: 1px solid rgba(25, 137, 191, 0.28);
  box-shadow: none;
  transition: background 220ms ease;
}

.mode-switch--knob .mode-switch__thumb::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 2px rgba(25, 137, 191, 0.35);
  transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

.mode-switch--knob:hover .mode-switch__thumb::after,
.mode-switch--knob:focus-within .mode-switch__thumb::after {
  transform: translateX(17px);
}

/* --- shared: the labels trade emphasis as the thumb passes --------------- */

.mode-switch--underline .mode-switch__current,
.mode-switch--knob .mode-switch__current { color: #12688f; font-weight: 700; }

.mode-switch--underline a.mode-toggle,
.mode-switch--underline a.mode-toggle:visited,
.mode-switch--knob a.mode-toggle,
.mode-switch--knob a.mode-toggle:visited { color: #93a4b3; font-weight: 600; }

.mode-switch--underline:hover .mode-switch__current,
.mode-switch--underline:focus-within .mode-switch__current,
.mode-switch--knob:hover .mode-switch__current,
.mode-switch--knob:focus-within .mode-switch__current { color: #7d97ad; font-weight: 600; }

.mode-switch--underline:hover a.mode-toggle,
.mode-switch--underline:focus-within a.mode-toggle,
.mode-switch--knob:hover a.mode-toggle,
.mode-switch--knob:focus-within a.mode-toggle {
  color: #12688f;
  font-weight: 700;
  background: none;
}

@media (prefers-reduced-motion: reduce) {
  .mode-switch__thumb,
  .mode-switch--knob .mode-switch__thumb::after { transition: none; }
}

/* On the Post-AI pages it lives in .nav__tools, inside a nav that is
   position: sticky; top: 0 -- so it is on screen at every scroll position
   without being a floating overlay. It sat fixed at bottom-left before and was
   reported as not always visible; the sticky nav is the design's own chrome
   and removes the question entirely. */
.nav__tools .mode-switch {
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border-color: color-mix(in srgb, var(--ink) 12%, transparent);
  font-size: 0.78rem;
}

.nav__tools .mode-switch__current {
  color: var(--ink);
  background: var(--surface);
}

.nav__tools a.mode-toggle,
.nav__tools a.mode-toggle:visited { color: var(--ink-3); }

.nav__tools a.mode-toggle:hover,
.nav__tools a.mode-toggle:focus-visible {
  color: var(--ink);
  background: color-mix(in srgb, var(--surface) 70%, transparent);
}

/* Non-desktop sees one design, so there is nothing for the switch to switch
   between: index.html redirects to post-ai.html on a coarse pointer or a
   viewport under 860px (the redirect lives in that file's <head>, and these
   two conditions must stay in step -- a control visible at a width the
   redirect also fires at would offer a round trip straight back here).
   This supersedes an earlier rule that merely SHRANK the switch at 40rem,
   whose comment read "the version switch must not [hide] -- it is the only
   route to the other design". That was true until the redirect existed; it is
   why the shrink rule is gone rather than narrowed.
   Both designs are covered: the classic page's switch sits in .name-line and
   the Post-AI one in .nav__tools, and .mode-switch is on both. */
@media (max-width: 860px), (pointer: coarse) {
  .mode-switch { display: none; }
}

/* --- the departure glitch ------------------------------------------------ */

/* The page you are leaving shudders, drains of colour and blows out to white;
 * the new design then loads clean.
 *
 * Why not the two-page wipe first sketched here: index.html and post-ai.html
 * are separate documents, and only the browser can hold both renderings on
 * screen across a navigation. That is cross-document @view-transition, which
 * ships in Chrome and Edge and in neither Firefox nor Safari -- so most of the
 * point (SEEING the two versions together) would have been invisible to a
 * large share of visitors. This animates only the document it can actually
 * reach, and therefore works everywhere.
 *
 * Everything below is transform, filter and opacity: compositor properties,
 * no layout, no reflow, and identical in quirks mode and standards mode.
 *
 * A filter on <body> makes it a containing block for fixed-position children,
 * so the floating toggle rides along with the glitch instead of hanging
 * motionless above it. That is the behaviour we want, and it lasts 620ms. */
html.mode-leaving { background: #ffffff; }

html.mode-leaving body {
  animation: mode-glitch 900ms steps(1, end) both;
  will-change: transform, filter, opacity;
}

@keyframes mode-glitch {
  0%   { transform: translate3d(0, 0, 0) skewX(0deg);       filter: none; opacity: 1; }
  8%   { transform: translate3d(-6px, 1px, 0) skewX(0.6deg); filter: saturate(0.85) contrast(1.15); }
  16%  { transform: translate3d(5px, -2px, 0) skewX(-0.9deg); filter: saturate(0.6) contrast(1.35) hue-rotate(6deg); }
  24%  { transform: translate3d(-9px, 0, 0) skewX(1.2deg);   filter: saturate(0.45) contrast(1.5); }
  33%  { transform: translate3d(7px, 2px, 0) skewX(-0.5deg); filter: saturate(0.3) contrast(1.7) hue-rotate(-8deg); }
  42%  { transform: translate3d(-4px, -1px, 0) skewX(0.8deg); filter: saturate(0.2) contrast(1.9); }
  52%  { transform: translate3d(10px, 1px, 0) skewX(-1.4deg); filter: saturate(0.1) contrast(2.2); opacity: 0.92; }
  62%  { transform: translate3d(-7px, 0, 0) skewX(0.4deg);   filter: grayscale(1) contrast(2.6); opacity: 0.8; }
  74%  { transform: translate3d(4px, -2px, 0) skewX(-0.7deg); filter: grayscale(1) contrast(3.4) brightness(1.5); opacity: 0.6; }
  86%  { transform: translate3d(-2px, 0, 0) skewX(0.2deg);   filter: grayscale(1) contrast(4) brightness(2.4); opacity: 0.32; }
  100% { transform: translate3d(0, 0, 0) skewX(0deg);        filter: grayscale(1) contrast(5) brightness(4); opacity: 0; }
}

/* --- the return ---------------------------------------------------------- */

/* Going back is not the glitch played backwards, and that is the point.
 *
 * The glitch says something about the direction it runs in: a hand-written page
 * tearing itself apart to become the AI-built one. Running the same violence in
 * reverse would say the original is what breaks, which is the wrong story and
 * also just looks like a bug the second time you see it.
 *
 * So the return settles instead. No jitter, no tearing, no hue shifts -- the
 * page loses its colour, softens, and recedes, the way something resolves
 * rather than fails. Smooth easing throughout against the glitch's stepped
 * timing, which is what makes the two read as different gestures rather than
 * two speeds of the same one. */
html.mode-returning body {
  animation: mode-settle 700ms cubic-bezier(0.4, 0, 0.2, 1) both;
  will-change: transform, filter, opacity;
}

@keyframes mode-settle {
  0%   { transform: scale(1);      filter: saturate(1) blur(0);      opacity: 1; }
  40%  { transform: scale(0.994);  filter: saturate(0.55) blur(1px); opacity: 0.85; }
  100% { transform: scale(0.985);  filter: saturate(0) blur(7px);    opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  html.mode-returning body { animation: none; }
}

/* No motion means no glitch. The navigation still happens -- it simply happens
   at once, which is what the site did before this existed. */
@media (prefers-reduced-motion: reduce) {
  html.mode-leaving body { animation: none; }
}

/* --- the arrival --------------------------------------------------------- */

/* The other half of the seam. The departing page dissolves away to its own
   background; without this the destination then appeared all at once, which is
   the hard cut that made an otherwise good glitch feel unfinished.
   Here the new page rises out of that same ground instead.

   The class is set by the synchronous <script> in each Post-AI page's <head>,
   BEFORE first paint -- which is the whole reason this works. An end-of-body
   script or a deferred module would run after the content is already on
   screen, so the page would flash at full opacity and then start fading, which
   is worse than no animation at all. That head script already exists to gate
   the reveal rules and restore the theme; this rides along with it rather than
   adding another.

   It deliberately does NOT hold the page hostage: the animation fills
   backwards from opacity 0, but if the class is never set, or the stylesheet
   fails to load, the page simply renders normally. */
html.mode-arriving body {
  animation: mode-arrive 620ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

@keyframes mode-arrive {
  0%   { opacity: 0; transform: scale(1.012); filter: blur(6px) saturate(0.6); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1);     filter: blur(0) saturate(1); }
}

/* The Post-AI page's own [data-reveal] sections animate in after this, so the
   two run in sequence: the page emerges, then its content builds. Holding the
   reveals back until the arrival finishes would double the wait for content. */

@media (prefers-reduced-motion: reduce) {
  html.mode-arriving body { animation: none; }
}
