/* Gabi Lipan — site foundation. Tokens come from the Visual Identity Guide v1.0. */

/* Self-hosted fonts (SIL Open Font License; files from Google Fonts, served from this site so no visitor's browser asks Google for anything).
   Wix Madefor Display and Text, and JetBrains Mono for code: variable fonts, Latin and Latin Extended. */
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("fonts/jetbrains-mono-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("fonts/jetbrains-mono-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Wix Madefor Display"; font-style: normal; font-weight: 500 800; font-display: swap; src: url("fonts/wix-madefor-display-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Wix Madefor Display"; font-style: normal; font-weight: 500 800; font-display: swap; src: url("fonts/wix-madefor-display-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Wix Madefor Text"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("fonts/wix-madefor-text-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Wix Madefor Text"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("fonts/wix-madefor-text-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }


:root {
  /* Palette (fixed, same in both themes) */
  --cyan: #28BFF6;
  --magenta: #FC4FD1;
  --yellow: #FAD746;
  --blue: #283BCA;
  --paper: #FCFBF8;
  --black: #171E21;

  /* Spacing scale: nothing in between */
  --s1: 8px; --s2: 16px; --s3: 28px; --s4: 48px; --s5: 80px; --s6: 128px;

  /* Type */
  --display: "Wix Madefor Display", system-ui, -apple-system, "Segoe UI", sans-serif;
  --text: "Wix Madefor Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;      /* code: its rounded-square shapes echo the squircles */

  /* Shape: every rounded corner on the site is a squircle (see .sq) */
  --r-card: 32px;
  --r-inner: 20px;
  --r-control: 14px;
  --r-pill: 999px;

  /* Spring easing: damped, one small overshoot (about 8%), settles in ~1s */
  --spring: cubic-bezier(.3, 1.4, .5, 1);
  --spring: linear(0, 0.0434, 0.1507, 0.2925, 0.4461, 0.5952, 0.729, 0.8417, 0.9308, 0.9967, 1.0416, 1.0686, 1.0812, 1.0832, 1.0777, 1.0677, 1.0554, 1.0426, 1.0304, 1.0197, 1.0109, 1.004, 0.999, 0.9957, 0.9939, 0.9931, 0.9931, 0.9937, 0.9946, 0.9957, 0.9967, 0.9977, 0.9986, 0.9993, 0.9998, 1.0002, 1);
  --spring-time: 0.95s;
  --spring-ui: 0.6s;

  /* Header */
  --safe-top: env(safe-area-inset-top, 0px);   /* the notch / status bar on phones (page is laid out under it: viewport-fit=cover) */
  --nav-h: 64px;          /* tall enough that nothing in the bar sits under the 11px Safari tint strip */
  --pill-h: 52px;
  --nav-pad: max(var(--s4), calc((100vw - 1280px) / 2 + var(--s4)));

  /* Light theme (default) */
  --bg: var(--paper);
  --fg: var(--black);
  --muted: rgba(23, 30, 33, 0.6);
  --surface: #F3F2EF;            /* black 4% over paper */
  --line: rgba(23, 30, 33, 0.14);
  --link: var(--blue);
  --focus: var(--blue);
  /* Code colours (on --surface). Every one is at least 4.5:1 against it, in both themes: `npm run check:contrast` keeps it so */
  --syn-keyword: #283BCA; --syn-string: #0B6B3A; --syn-number: #A8137F; --syn-comment: #566166; --syn-function: #6137B8;
  --syn-type: #0A6683; --syn-property: #8A4A06; --syn-op: #3A4448; --syn-gutter: #5F686C; --syn-invalid: #B3261E;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: var(--black);
    --fg: var(--paper);
    --muted: rgba(252, 251, 248, 0.6);
    --surface: #252B2E;          /* paper 6% over black */
    --line: rgba(252, 251, 248, 0.16);
    --link: var(--cyan);
    --focus: var(--cyan);
    --syn-keyword: #5AC8FA; --syn-string: #86DDA0; --syn-number: #FF92E3; --syn-comment: #9DA8AD; --syn-function: #CDB0FF;
    --syn-type: #63D6EC; --syn-property: #F4C676; --syn-op: #C9D1D4; --syn-gutter: #8D989D; --syn-invalid: #FF8A80;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: var(--black);
  --fg: var(--paper);
  --muted: rgba(252, 251, 248, 0.6);
  --surface: #252B2E;
  --line: rgba(252, 251, 248, 0.16);
  --link: var(--cyan);
  --focus: var(--cyan);
  --syn-keyword: #5AC8FA; --syn-string: #86DDA0; --syn-number: #FF92E3; --syn-comment: #9DA8AD; --syn-function: #CDB0FF;
  --syn-type: #63D6EC; --syn-property: #F4C676; --syn-op: #C9D1D4; --syn-gutter: #8D989D; --syn-invalid: #FF8A80;
  color-scheme: dark;
}

/* ── Base ─────────────────────────────────────────────────── */

* { box-sizing: border-box; }

html { scroll-padding-top: calc(88px + var(--safe-top)); background: var(--bg); }

body {
  margin: 0;
  padding-top: calc(var(--nav-h) + var(--safe-top));
  background: var(--bg);
  color: var(--fg);
  font: 400 17px/1.62 var(--text);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.05;
}

p { margin: 0; }
a { color: inherit; }

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

.skip { position: absolute; left: var(--s2); top: -100px; padding: var(--s1) var(--s2); background: var(--fg); color: var(--bg); z-index: 20; }
.skip:focus { top: var(--s2); }

.page { max-width: 1280px; margin: 0 auto; padding: 0 var(--s4); }

/* ── Squircle corners ─────────────────────────────────────────
   border-radius gives the fallback (plain rounding); corner-shape
   upgrades it to a continuous curve where the browser supports it.
   Containers are squircles. Controls (buttons, fields, toggles) are
   full pills, which stay ordinary circular caps. */
.surface, .shot { corner-shape: squircle; }

/* ── Header ──────────────────────────────────────────────────
   At the top of the page the header is a plain bar that belongs to the page and scrolls
   away with it. Once you scroll, the same content moves into a floating pill that is fixed,
   12px below the top edge, and drops in with a bounce.
   Nothing fixed ever touches the very top edge. That is deliberate: Safari 26 colours its
   toolbar from a fixed element it finds there, and with none it draws see-through glass
   over the page, tinted by the page itself, which follows the theme on its own. */

.nav-bar { position: absolute; top: 0; left: 0; right: 0; z-index: 10; padding-top: var(--safe-top); }

.nav-pill {
  position: fixed; top: calc(12px + var(--safe-top)); left: 50%; z-index: 10;
  width: min(calc(1280px - 2 * var(--s4)), calc(100% - 24px));   /* as wide as the content */
  transform: translateX(-50%);
  pointer-events: none;
}
.nav-pill[hidden] { display: none; }

.nav-inner {
  --row-h: var(--nav-h);
  position: relative; pointer-events: auto;
  height: var(--row-h);
  padding: 0 var(--nav-pad);
  border: 1px solid transparent; border-bottom-color: var(--line);
  background: var(--bg);
  font-size: 15px;
}
.nav-row { display: flex; align-items: center; gap: var(--s3); height: calc(var(--row-h) - 2px); }

.nav-pill .nav-inner {
  --row-h: var(--pill-h);
  padding: 0 10px 0 18px;
  border-color: var(--line);
  border-radius: calc(var(--pill-h) / 2);
  background: none;
  animation: pill-in .9s var(--spring) both;
}
/* The pill's frosted glass is a layer of its own, behind the header's content and not part of
   it. nav.js keeps a hole cut in it exactly under the menu button and the toggle (--glass-clip,
   updated every frame so the hole and the control always move as one). Each of those controls
   then has its own, lighter glass that sees the page directly, instead of only the pill's
   already frosted surface. */
.nav-pill::before {
  content: ""; position: absolute; inset: 0; border-radius: calc(var(--pill-h) / 2);
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  -webkit-backdrop-filter: blur(22px) saturate(1.8);
          backdrop-filter: blur(22px) saturate(1.8);
  clip-path: var(--glass-clip, none);
  animation: pill-in .9s var(--spring) both;
}
.nav-pill:has(.nav-inner.settled)::before { animation: none; }
.nav-pill .nav-inner.settled { animation: none; }          /* page opened already scrolled */
.nav-bar .nav-inner.arriving { animation: bar-in .4s ease-out both; }

/* No fade here on purpose: an element with an animated opacity cuts its children off from
   the page behind it, which would switch the glass layers inside the pill off. The pill
   starts above the top edge of the screen anyway, so it drops in without a fade. */
@keyframes pill-in {
  from { transform: translateY(-64px) scale(0.92); }
  to   { transform: none; }
}
@keyframes bar-in {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}

/* On phones the pill does not drop from above the screen. For that moment it touches the top edge,
   and Safari on iPhone takes it for a header and paints a solid band behind the notch, which stays
   until a fast scroll stops. Instead it grows in where it rests, from its top edge, with the same
   spring, and fades in. Each layer fades on its own (the glass, the border, the logo, the button):
   fading the whole pill would switch its glass off, as explained above. */
@media (max-width: 700px), (max-height: 500px) and (pointer: coarse) {
  .nav-pill .nav-inner { animation-name: pill-grow; transform-origin: 50% 0; }
  .nav-pill::before { animation-name: pill-grow-glass; transform-origin: 50% 0; }
  .nav-pill .nav-row > * { animation: pill-fade .4s ease-out both; }
  .nav-pill .nav-inner.settled .nav-row > * { animation: none; }
}
@keyframes pill-grow       { from { transform: scale(.9); border-color: transparent; } }
@keyframes pill-grow-glass { from { transform: scale(.9); opacity: 0; } }
@keyframes pill-fade       { from { opacity: 0; } }

.brand { display: flex; align-items: center; gap: 10px; margin-right: auto; font: 700 17px var(--display); letter-spacing: -0.02em; text-decoration: none; white-space: nowrap; }
.brand svg { width: 28px; height: 28px; flex: none; }
.nav-links { display: flex; gap: var(--s3); }
.nav-links a, .menu-panel a { color: var(--muted); text-decoration: none; }
.nav-links a:hover, .menu-panel a:hover { color: var(--fg); }

/* A header link with sub-pages: a small panel opens under it on hover or focus. The panel starts right
   at the link's foot (padding bridges the gap), so the pointer can travel into it without it closing. */
.nav-links { align-items: center; }
.nav-sub { position: relative; }
.nav-sub > a { display: inline-flex; align-items: center; gap: 4px; }
.nav-caret { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; transition: transform .4s var(--spring); }
.nav-sub:hover .nav-caret, .nav-sub:focus-within .nav-caret, .nav-sub.is-open .nav-caret { transform: rotate(180deg); }
.nav-drop { position: absolute; top: 100%; left: 50%; z-index: 5; padding-top: 18px; transform: translate(-50%, -6px); opacity: 0; visibility: hidden; transition: opacity .2s, transform .45s var(--spring), visibility 0s .2s; }
.nav-sub:hover .nav-drop, .nav-sub:focus-within .nav-drop, .nav-sub.is-open .nav-drop { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition-delay: 0s; }
.nav-drop-in { display: grid; gap: 2px; min-width: 180px; padding: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-inner); corner-shape: squircle; }
.nav-drop-in a { display: block; padding: 9px 14px; border-radius: 12px; white-space: nowrap; }
.nav-drop-in a:hover { background: var(--surface); }
.menu-panel a.menu-sub { font: 500 20px/1.2 var(--display); letter-spacing: -0.02em; color: var(--muted); padding: 2px 0; }
.menu-panel a.menu-sub:hover { color: var(--fg); }

/* Theme toggle: collapsed to the current icon, springs open on hover.
   Dragging or clicking moves a liquid thumb (animated in theme.js). */
.seg {
  --slot: 30px; --seg-pad: 3px;
  position: relative; flex: none; box-sizing: content-box;
  width: var(--slot); height: var(--slot); padding: var(--seg-pad);
  overflow: hidden;
  background: color-mix(in srgb, var(--fg) 7%, transparent); -webkit-backdrop-filter: blur(8px) saturate(1.5); backdrop-filter: blur(8px) saturate(1.5); border-radius: var(--r-pill);
  cursor: pointer; touch-action: none;
  -webkit-user-select: none; user-select: none;
  transition: width var(--spring-ui) var(--spring);
}
.seg[data-open] { width: calc(var(--slot) * 3); }

.seg-track {
  position: relative; display: flex;
  width: calc(var(--slot) * 3); height: var(--slot);
  /* --i is set on the toggle by theme.js; until then the page's head script has put the saved
     position in --seg-i on <html>, so the strip starts where it belongs instead of sliding there */
  transform: translateX(calc(var(--i, var(--seg-i, 0)) * var(--slot) * -1));
  transition: transform var(--spring-ui) var(--spring);
}
.seg[data-open] .seg-track { transform: none; }

.seg-thumb {
  position: absolute; left: 0; top: 0;
  width: var(--slot); height: var(--slot);
  background: var(--bg); border-radius: var(--r-pill);
  box-shadow: 0 0 0 1px var(--line);
  transform: translateX(calc(var(--seg-i, 0) * var(--slot)));   /* theme.js takes over with the same position */
  pointer-events: none;
}

.seg button {
  position: relative; z-index: 1; flex: none;
  display: grid; place-items: center;
  width: var(--slot); height: var(--slot); padding: 0;
  background: none; border: 0; border-radius: 50%;
  color: var(--muted); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.seg button svg { width: var(--ico, 16px); height: var(--ico, 16px); fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.seg button:hover { color: var(--fg); }
.seg button[aria-checked="true"] { color: var(--fg); }
.seg button:focus-visible { outline-offset: -2px; }

/* Small screens: the bar grows taller to hold the menu.
   The button is a circle; its two bars turn into an X when the menu is open. */
.menu-btn { display: none; place-items: center; width: 40px; height: 40px; flex: none; padding: 0; background: color-mix(in srgb, var(--fg) 7%, transparent); -webkit-backdrop-filter: blur(8px) saturate(1.5); backdrop-filter: blur(8px) saturate(1.5); color: var(--fg); border: 0; border-radius: 50%; cursor: pointer; transition: background-color .2s, transform .45s var(--spring); }
.menu-btn:active { transform: scale(.9); }
.menu-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; overflow: visible; }
.menu-btn path { transform-box: fill-box; transform-origin: center; transition: transform .6s var(--spring); }
.nav-inner[data-menu="open"] .menu-btn .l1 { transform: translateY(2.5px) rotate(45deg) scaleX(1.12); }
.nav-inner[data-menu="open"] .menu-btn .l2 { transform: translateY(-2.5px) rotate(-45deg) scaleX(1.12); }

/* The menu items sit on the right, where the thumb tapped, and ripple in one after another */
.menu-panel { display: none; justify-items: end; gap: 2px; padding: 6px 22px 24px; text-align: right; }
.menu-panel a { display: block; padding: 6px 0; color: var(--fg); font: 700 28px/1.15 var(--display); letter-spacing: -0.03em; text-decoration: none; }
.menu-panel .menu-seg { margin-top: var(--s2); }
.menu-panel .seg { -webkit-backdrop-filter: none; backdrop-filter: none; }   /* on the pill's glass, no glass of its own (see nav.js) */
.menu-panel > * {
  opacity: 0; visibility: hidden; transform: translateY(-12px); filter: blur(5px);
  transition: opacity .2s ease, transform .3s ease, filter .2s ease, visibility 0s .3s;
}
.nav-inner[data-menu="open"] .menu-panel > * {
  opacity: 1; visibility: visible; transform: none; filter: none;
  transition:
    opacity .45s ease calc(var(--i, 0) * 60ms + 130ms),
    transform .9s var(--spring) calc(var(--i, 0) * 60ms + 130ms),
    filter .45s ease calc(var(--i, 0) * 60ms + 130ms),
    visibility 0s 0s;
}

/* ── Shared components ────────────────────────────────────── */

.link { color: var(--link); font-weight: 500; text-decoration: none; }
.link:hover { text-decoration: underline; }
.muted { color: var(--muted); }

.surface { background: var(--surface); border-radius: var(--r-card); }

.shot {
  display: grid; place-items: center;
  aspect-ratio: 16 / 10;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-inner);
  color: var(--muted); font-size: 13px;
}

.btn {
  display: inline-block; padding: 14px 26px;
  background: var(--yellow); color: var(--black);
  font: 600 17px var(--text); text-decoration: none;
  border: 0; border-radius: var(--r-pill); cursor: pointer;
}
.btn:hover { filter: brightness(0.96); }

.field {
  width: 100%; padding: 14px 24px;
  background: transparent; color: inherit;
  font: 400 17px var(--text);
  border: 1px solid currentColor; border-radius: var(--r-pill);
}
.field::placeholder { color: inherit; opacity: 0.7; }
.field:focus-visible { outline-color: var(--yellow); }

/* ── Home ─────────────────────────────────────────────────── */

.hero { text-align: center; padding: var(--s6) 0 var(--s5); }
.hero .mk { width: 72px; height: 72px; margin-bottom: var(--s4); overflow: visible; }
.hero h1 { max-width: 17ch; margin: 0 auto; font-size: clamp(38px, 5.4vw, 64px); letter-spacing: -0.045em; }
.hero p { max-width: 40ch; margin: var(--s3) auto 0; color: var(--muted); font-size: 19px; }
.hero .links { display: flex; gap: var(--s3); justify-content: center; margin-top: var(--s3); font-size: 19px; }

.feature { padding-bottom: var(--s5); }
.feature .surface { padding: var(--s4); }

.work { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); padding-bottom: var(--s5); }
.work .surface { display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4) var(--s4) var(--s3); }
.work h2 { font-size: 28px; }
.meta { font-size: 13px; color: var(--muted); }

.band { background: var(--blue); color: var(--paper); text-align: center; padding: var(--s6) 0; }
.band h2 { max-width: 16ch; margin: 0 auto; font-size: clamp(34px, 4.6vw, 52px); }
.band p { margin: var(--s2) auto 0; max-width: 38ch; opacity: 0.85; }
.band form { display: flex; gap: var(--s2); justify-content: center; max-width: 520px; margin: var(--s4) auto 0; }
.band .field { flex: 1; min-width: 0; }

.foot { border-top: 1px solid var(--line); font-size: 13px; color: var(--muted); }
.foot .page { display: flex; gap: var(--s3); padding-top: var(--s3); padding-bottom: var(--s3); }
.foot .page span:first-child { margin-right: auto; }
.foot a { text-decoration: none; }
.foot a:hover { color: var(--fg); }

/* The one animated moment: the mark assembles, once.
   Pink disc pops, the blue dot docks (cyan where it overlaps), a clock hand wipes its right half,
   the square slides in and turns 180° to carry its cyan wedge to the corner, taking that piece of the disc with it.
   Timings come from the study page, system/logo-animation/. */
.mk .popper    { transform-box: fill-box; transform-origin: 50% 50%; animation: mk-pop 650ms cubic-bezier(.3, 1.5, .55, 1) both; }
.mk .dot-move  { animation: mk-arrive 1100ms 400ms cubic-bezier(.2, .75, .25, 1) both; }
.mk .dot-blue  { animation: mk-arrive 1100ms 400ms cubic-bezier(.2, .75, .25, 1) both, mk-vanish 1ms 1500ms linear forwards; }
.mk .dot-solid { animation: mk-vanish 1ms 750ms linear both; }
.mk .dot       { stroke-dasharray: 157.08 157.08; animation: mk-clock 1270ms 750ms cubic-bezier(.45, 0, .4, 1) both; }
.mk .sq-move   { animation: mk-slide 850ms 900ms cubic-bezier(.2, .75, .25, 1) both; }
.mk .sq-spin   { animation: mk-turn 800ms 1900ms cubic-bezier(.7, 0, .2, 1) both; }
.mk .bite      { animation: mk-appear 1ms 1900ms linear both; }  /* the disc's quarter under the wedge goes as the turn starts */
@keyframes mk-pop    { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes mk-arrive { 0% { transform: translate(-190px, 190px) scale(.55); opacity: 0; } 35% { opacity: 1; } 100% { transform: translate(0, 0) scale(1); opacity: 1; } }
@keyframes mk-vanish { from { opacity: 1; } to { opacity: 0; } }
@keyframes mk-appear { from { opacity: 0; } to { opacity: 1; } }
@keyframes mk-clock  { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -78.54; } }  /* half the ring, 12 → 6 */
@keyframes mk-slide  { 0% { transform: translate(160px, -160px) scale(.55); opacity: 0; } 35% { opacity: 1; } 100% { transform: translate(0, 0) scale(1); opacity: 1; } }
@keyframes mk-turn   { from { transform: rotate(0deg); } to { transform: rotate(180deg); } }

@media (prefers-reduced-motion: reduce) {
  /* jump straight to the finished mark (removing the animations would leave the parts unassembled) */
  .mk * { animation-duration: 1ms !important; animation-delay: 0s !important; }
  .seg, .seg-track { transition: none; }
  .nav-inner, .nav-pill::before, .nav-pill .nav-row > * { animation: none !important; }
}

@media (max-width: 800px) {
  .page { padding: 0 var(--s2); }
  .hero { padding: var(--s5) 0 var(--s4); }
  .work { grid-template-columns: 1fr; }
  .feature .surface, .work .surface { padding: var(--s3) var(--s2) var(--s2); }
  .band { padding: var(--s5) 0; }
  .band form { flex-direction: column; }
  .foot .page { flex-wrap: wrap; }
}

@media (max-width: 700px) {
  :root { --nav-pad: var(--s2); }
  .nav-links, .nav-row > .seg { display: none; }
  .menu-btn { display: grid; }
  .nav-pill .nav-inner { padding: 0 6px 0 18px; }          /* the circle sits evenly inside the pill's end */
  .nav-inner { overflow: hidden; transition: height .4s cubic-bezier(.3, 0, .2, 1), background-color .3s ease; }
  .nav-inner[data-menu="open"] { height: calc(var(--row-h) + var(--menu-h, 320px)); transition: height var(--spring-time) var(--spring), background-color .3s ease; }
  .menu-panel { display: grid; }
}

/* ── Theme change: a sunrise or sunset spreads from the toggle ─
   The new theme is revealed through a soft-edged shape that grows from the toggle: a circle with
   big lobes that drift and pulse, built from a few soft radial gradients that sweep.js redraws
   every frame. A glow rides the leading edge. Same in every browser. --sun-r is only a timer.

   How: the moment the toggle is pressed, sweep.js lays a copy of the page over the page, in the
   old colours, and the page itself switches to the new ones. The shape is cut out of the copy, so
   the new page shows through it as it grows. The copy is ordinary page content: nothing is pinned
   to the screen. That matters on iPhone, where Safari paints solid bars behind the notch and the
   address bar whenever something pinned touches the screen's edges. (The browser's own View
   Transitions work by pinning a picture of the old page over the screen, which is why they are
   not used. The study page, system/theme-animation/, records the options that were tried.) */

@property --sun-r { syntax: "<length>"; inherits: true; initial-value: 0px; }

/* The copy covers the visible part of the page (plus a margin), not all of it, so the browser
   only has to mask a screenful. sweep.js keeps it where the screen is, even while scrolling.
   It is cut off hard at its edges (clip and paint containment, not just hidden): a copied pinboard
   reaches far past the right edge, and Safari on iPhone widened the page for it and kept the
   page a little wider than the screen after the change, until a reload. */
.sweep-copy {
  position: absolute; left: 0; width: 100%; z-index: 60;
  overflow: hidden; overflow: clip; contain: layout paint; pointer-events: none;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.sweep-page {
  position: relative;
  padding-top: calc(var(--nav-h) + var(--safe-top));        /* the same box as the body */
  background: var(--bg); color: var(--fg);
}
/* Nothing in the copy moves: animations show their last frame, and nothing transitions */
.sweep-page *, .sweep-page *::before, .sweep-page *::after {
  animation-delay: -60s !important; animation-play-state: paused !important; transition: none !important;
}
.sweep-page .nav-pill { position: absolute; }               /* the floating header, held in place by sweep.js */

/* The glow lies over the visible part of the page, under the copy, so it only shows inside the
   shape. It is not pinned to the screen either, for the same reason as the copy. */
#sun-glow {
  display: none; position: absolute; left: 0; width: 100%; z-index: 55; pointer-events: none;
  top: var(--sun-top, 0px); height: var(--sun-h, 100vh);
}
html[data-sun] #sun-glow { display: block; background: var(--sun-glow-image); }

/* ── Safari toolbar at the top of the page ───────────────────
   Safari's glass toolbar only turns dark once enough of the page has slid under it. At the
   top of the page, and for the first stretch of scrolling, there is little or nothing under
   it, so it shows its own lighter default material. The only way to give it our colour
   meanwhile is a solid, full-width, fixed element touching the top edge, more than 10px tall.
   This is that element, in the page colour and sitting on top of the bar, so it cannot be
   seen. nav.js switches it off once you have scrolled far enough (about 120px) for the glass
   to be dark by itself, and back on if you return to the top. Only used in Safari (the class
   is added in the page head). */
#tint { display: none; }
html.safari-tint:not(.scrolled) #tint {
  display: block;
  position: fixed; top: 0; left: 0; width: 100%; height: 11px;
  background-color: var(--bg);
  z-index: 11;
}
/* Not on phones. There Safari only re-checks the strip once a scroll settles, so after a quick flick
   it kept a solid band behind the notch with the page sliding under it, and during a theme change
   the band jumped to the new colour ahead of the sunrise. Phones get Safari's own glass instead. */
@media (max-width: 700px), (max-height: 500px) and (pointer: coarse) {
  html.safari-tint:not(.scrolled) #tint { display: none; }
}

/* On phones the theme toggle is always open, and bigger, easier to hit with a thumb. Tablets and
   wider touch screens keep the desktop toggle: the first tap opens it (see theme.js). */
@media (max-width: 700px) {
  .seg { --slot: 40px; --seg-pad: 4px; --ico: 20px; width: calc(var(--slot) * 3); }
  .seg-track { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .nav-inner, .menu-panel > *, .menu-btn path, .menu-btn { transition: none !important; }
  .menu-panel > * { filter: none; transform: none; }
}
