/* Shared foundation for every page on eoblend.com: tokens, section themes,
   typography, header, footer, reveal states. Loaded first; landing.css (the
   notebook shell) and page.css (long-form documents) build on it. */

:root {
  /* Squarespace site palette the design came from, named by colour. Dark mode
     keeps the names and swaps the values, so nothing downstream has to know
     which theme is on — see the [data-theme="dark"] block below. */
  --cream:#f6f3ee;
  --beige:#f3ece2;
  --gold:#ecaf2b;
  --charcoal:#444340;
  --pink:#fee9e7;

  /* Roles, for the jobs --charcoal used to do alone. It played three at once —
     ink, dark surface, and the label on gold — and they part company in dark
     mode, where ink turns pale while the other two stay dark. */
  --ink:var(--charcoal);          /* body text, headings, borders */
  --ink-rgb:68 67 64;             /* the same, for translucent rules */
  --deep:var(--charcoal);         /* a solid dark control: button, chip */
  --band:#232221;                 /* the closing section's ground, darker still */
  --on-deep:var(--beige);         /* text on --deep and --band */
  --on-accent:var(--charcoal);    /* text on gold, which is dark in both modes */
  --gold-rgb:243 181 46;          /* --gold, for translucent tints of it */
  --gold-hover:#f3b52e;
  --amber-deep:#805608;           /* the accent, readable on a pale ground */
  --shadow-rgb:68 67 64;
  --focus:#745008;
  --focus-halo:#fff;              /* the ring's outer half, against any section */
  --logo-filter:none;             /* set where the wordmark's ground flipped */

  --heading-font:'Averia Serif Libre',Georgia,'Times New Roman',serif;
  --body-font:'Open Sans',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;

  --radius:24px;
  --container:1140px;
  /* Colour of the page's first section, so the canvas can match it. */
  --page-top:var(--beige);
  color-scheme: light;

  /* The notch and home-indicator strips. Each page's viewport meta carries
     viewport-fit=cover, which puts them inside the layout viewport so the
     sections paint through them instead of leaving iOS to fill them white;
     the padding below is what then keeps content off the hardware. The 0px
     fallback covers every browser that has no such strips. */
  --safe-t:env(safe-area-inset-top, 0px);
  --safe-b:env(safe-area-inset-bottom, 0px);
  --safe-l:env(safe-area-inset-left, 0px);
  --safe-r:env(safe-area-inset-right, 0px);
}

/* Dark theme ----------------------------------------------------------
   An inversion, not a second palette. Only the pale neutrals flip: where the
   ground was cream or beige it goes dark, and the charcoal text that sat on it
   goes pale. Gold and pink are the same colours in both themes, so the gold
   band, the pink band and the footer come through untouched — and so does the
   charcoal band, which was already dark and has nothing to invert.

   The dark values stay in --charcoal's warm grey family rather than going to
   black, so the page reads as the same site with the lights off.

   theme.js sets data-theme on <html> before first paint, from the stored
   choice or the OS. */
:root[data-theme="dark"] {
  /* The app's dark ground, so the site and the screenshots on it match. */
  --cream:#1c1917;    /* the pale surface, flipped: header, cards, most sections */
  --beige:#181513;    /* a step deeper, as beige sat a step under cream */
  /* --gold, --pink and --charcoal keep their light values. */

  /* The charcoal text becomes light mode's cream — a palette colour, not a new
     one. --on-deep follows it, since --beige is no longer pale. */
  --ink:#f6f3ee;
  --ink-rgb:246 243 238;
  --on-deep:#f6f3ee;
  /* --deep, --on-accent, --gold-hover are unchanged: those surfaces don't flip. */

  /* Gold on a dark ground needs no deepening — that was for pale sections. */
  --amber-deep:var(--gold);
  /* A pale shadow would glow; on this ground shadows go to black. */
  --shadow-rgb:0 0 0;
  --focus:var(--gold);
  --focus-halo:#000;
  /* The wordmark artwork is flat near-black on transparency and would vanish
     on a flipped ground. brightness(0) flattens it to black whatever shade it
     started at, so the invert lands on white rather than the soft grey a plain
     invert of #2b2b2b gives; the sepia takes the edge off. */
  --logo-filter:brightness(0) invert(1) sepia(.06);

  /* --page-top is left alone: it is declared as var(--beige) / var(--cream),
     which re-resolve to the values above, so each page's canvas follows. */
  color-scheme: dark;
}

/* The gold band, the pink band, the footer and the charcoal band all end up
   with a pale interior in dark mode — the first three because they kept their
   colour, the last because it turns pale (see below). So they are light-mode
   islands: everything inside them — ink, hairlines, the pale chips and cards
   they hold, the focus ring — goes back to its light value. Putting the light
   palette back on the section itself means every child follows, including the
   page-level overrides in landing.css. */
:root[data-theme="dark"] :is(.theme-bright, .theme-dark, .theme-light, .site-footer) {
  --cream:#f6f3ee;
  --beige:#f3ece2;
  --ink:var(--charcoal);
  --ink-rgb:68 67 64;
  --amber-deep:#805608;
  --focus:#745008;
  --focus-halo:#fff;
  --shadow-rgb:68 67 64;
  /* Including the wordmark: the document pages' header sits inside the pink
     band, where the dark artwork still reads. */
  --logo-filter:none;
}

/* The charcoal band is the page's odd one out — the single dark block on a
   pale page. Dark mode swaps its two ends rather than leaving it be, so it
   stays the odd one out instead of merging into the dark around it: the
   ground takes the colour its text had, and the text takes the ground's.
   Only the closing section wears this theme. */
:root[data-theme="dark"] .theme-light {
  --bg:var(--beige);
  --heading:var(--ink);
  --body:var(--ink);
}

* { box-sizing:border-box; }

/* Theme switch ---------------------------------------------------------
   Flipping data-theme changes a few tokens and every painted colour on the
   page follows at once, so without this the switch is a hard cut. The
   transition is only mounted while it is needed: theme.js puts
   .theme-switching on <html> for the length of the fade and takes it off
   again. A standing transition on every element would fire on first paint,
   and would slow every hover for the rest of the visit.

   Colour properties only. transform and opacity are left alone so the scroll
   reveals and the button's press keep their own timing. */
@media (prefers-reduced-motion:no-preference) {
  :root.theme-switching,
  :root.theme-switching *,
  :root.theme-switching *::before,
  :root.theme-switching *::after {
    transition:
      background-color 320ms ease,
      color 320ms ease,
      border-color 320ms ease,
      outline-color 320ms ease,
      box-shadow 320ms ease,
      fill 320ms ease,
      stroke 320ms ease,
      filter 320ms ease !important;
    transition-delay:0s !important;
  }
}

/* What iOS paints when you rubber-band past either end of the page. The
   gradient looks upside-down on purpose: a root background tiles across the
   canvas but is positioned to the root box, so the halves that actually show
   are the repeats either side of the document. The half inside the document is
   never seen, since every section paints over it. */
html {
  /* The shorthand alone leaves background-color transparent, which iOS renders
     as white on any strip it fills from the root rather than from a section. */
  background-color:var(--page-top);
  background-image:linear-gradient(var(--gold) 0 50%, var(--page-top) 50% 100%);
}

body {
  margin:0;
  font-family:var(--body-font);
  font-size:1.0625rem;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}

/* Section themes ------------------------------------------------------
   Each theme fills the same four slots, so any section can wear any theme and
   its children pick up the right colours. */
.theme-bright-inverse { --bg:var(--beige);    --heading:var(--gold);  --body:var(--ink);     --btn-bg:var(--gold);  --btn-fg:var(--on-accent); }
.theme-bright         { --bg:var(--gold);     --heading:var(--beige); --body:var(--beige);   --btn-bg:var(--beige); --btn-fg:var(--gold);      }
.theme-dark           { --bg:var(--pink);     --heading:var(--ink);   --body:var(--ink);     --btn-bg:var(--cream); --btn-fg:var(--ink);       }
.theme-light          { --bg:var(--band);     --heading:var(--on-deep); --body:var(--on-deep); --btn-bg:var(--beige); --btn-fg:var(--ink);     }
.theme-cream          { --bg:var(--cream);    --heading:var(--ink);   --body:var(--ink);     --btn-bg:var(--gold);  --btn-fg:var(--on-accent); }

/* overflow:hidden contains the wave, which is wider than the viewport. */
section { background:var(--bg); color:var(--body); overflow:hidden; }
.section-pad { padding:clamp(64px,9vw,118px) 24px; }
/* Landscape on a notched phone eats into one side; 24px stays the floor. */
.section-pad { padding-left:max(24px, var(--safe-l)); padding-right:max(24px, var(--safe-r)); }
.pad-lg { padding-top:clamp(132px,17vw,232px); padding-bottom:clamp(132px,17vw,232px); }
.pad-sm { padding-top:clamp(38px,4.5vw,60px);  padding-bottom:clamp(38px,4.5vw,60px); }
.container { max-width:var(--container); margin:0 auto; }

/* Boundary between two sections. Sits as the first child of the lower section,
   filled with the upper section's colour. The negative margin closes the
   subpixel seam some browsers leave under a scaled SVG. */
.wave {
  display:block; width:200%;
  height:clamp(58px,7.5vw,124px);
  margin-bottom:-1px;
  fill:var(--pink);
}

/* Typography ----------------------------------------------------------
   Fluid versions of the design's 4 / 2.8 / 2.2 / 1.6rem scale, so headings
   don't overflow on a phone. */
h1, h2, h3, h4 {
  font-family:var(--heading-font); font-weight:400;
  letter-spacing:-.02em; line-height:1.2;
  color:var(--heading); margin:0;
}
h1 { font-size:clamp(2.6rem,6.4vw,4rem); }
h2 { font-size:clamp(2rem,4.6vw,2.8rem); }
h3 { font-size:clamp(1.5rem,3.2vw,2.2rem); }
h4 { font-size:clamp(1.25rem,2.2vw,1.6rem); }
p { margin:0; }
.lead { font-size:1.15rem; max-width:52ch; }

a { color:inherit; }

/* Apple's official "Download on the App Store" badge artwork. */
.badge { display:inline-block; line-height:0; transition:transform .15s ease; }
.badge img { width:186px; height:auto; }
.badge:hover { transform:translateY(-2px); }

/* Header --------------------------------------------------------------- */
.site-header {
  padding:calc(26px + var(--safe-t)) max(24px, var(--safe-r)) 0 max(24px, var(--safe-l));
}
/* Full width rather than the centred column, so the logo sits out at the page
   edge instead of being inset with the rest of the content. The theme toggle
   takes the far end. */
.site-header .container {
  display:flex; justify-content:space-between; align-items:center;
  gap:16px; max-width:none;
}
.site-header img { width:210px; height:auto; display:block; }

/* Theme toggle ---------------------------------------------------------
   One button, both icons inside it: the sun shows in dark mode and the moon in
   light, so the icon always names where the click leads. No-JS pages never get
   data-theme, and theme.js only unhides the button once it can act, so a
   dead control is never painted. */
.theme-toggle {
  /* The ring and the icon, as one colour. Dark mode hands it the gold. */
  --toggle-ink:currentColor;
  --toggle-ink-rgb:var(--ink-rgb);
  display:none;
  flex:0 0 auto;
  width:40px; height:40px; padding:0;
  align-items:center; justify-content:center;
  border:1px solid rgb(var(--toggle-ink-rgb) / .22);
  border-radius:999px;
  background:transparent;
  color:var(--toggle-ink);
  cursor:pointer;
  transition:background-color 180ms ease, border-color 180ms ease, transform 180ms ease;
}
/* The sun is gold on the flipped ground. Not inside the sections that kept
   their colour — there the header is light mode's and so is its toggle. */
:root[data-theme="dark"] .theme-toggle {
  --toggle-ink:var(--gold);
  --toggle-ink-rgb:var(--gold-rgb);
}
/* Gold on pale pink is 1.9:1, so the document pages' header — which sits
   inside the pink band — keeps the light-mode toggle. Set on the button, not
   inherited, because the rule above sets it on the button too. */
:root[data-theme="dark"] :is(.theme-bright, .theme-dark, .site-footer) .theme-toggle {
  --toggle-ink:currentColor;
  --toggle-ink-rgb:68 67 64;
}
/* Grid rather than flex, so both icons share one cell and can cross-fade in
   place: hiding the outgoing one with display would make it jump. */
:root[data-theme] .theme-toggle { display:inline-grid; }
.theme-toggle svg { grid-area:1 / 1;
  width:19px; height:19px; display:block; fill:none;
  stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round;
  transition:opacity 260ms ease, transform 320ms ease; }
/* The crescent is one closed shape, so filling it reads as a solid dark moon
   rather than the hairline outline a stroke alone leaves. The sun stays open:
   filling it would swallow the gap between the disc and its rays. */
.theme-toggle .icon-moon { fill:currentColor; }
/* Each icon turns out of the way as the other turns in. */
.theme-toggle .icon-sun { opacity:0; transform:rotate(-80deg) scale(.5); }
:root[data-theme="dark"] .theme-toggle .icon-sun { opacity:1; transform:none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { opacity:0; transform:rotate(80deg) scale(.5); }
/* The blanket colour transition above would drop these two, since it names no
   opacity or transform. More specific, so this is the one that applies. */
:root.theme-switching .theme-toggle svg {
  transition:opacity 260ms ease, transform 320ms ease, stroke 320ms ease, fill 320ms ease !important;
}
@media (hover:hover) and (pointer:fine) {
  .theme-toggle:hover {
    background:rgb(var(--toggle-ink-rgb) / .12);
    border-color:rgb(var(--toggle-ink-rgb) / .55);
  }
}
.theme-toggle:active { transform:scale(.94); }
@media (prefers-reduced-motion:reduce) {
  .theme-toggle, .theme-toggle svg { transition:none; }
  .theme-toggle:active { transform:none; }
  /* Still hidden, just without the turn. */
  .theme-toggle .icon-sun { transform:none; }
  :root[data-theme="dark"] .theme-toggle .icon-moon { transform:none; }
}

/* Footer --------------------------------------------------------------- */
/* Gold, but not via .theme-bright: that theme's beige text lands at 1.8:1 on
   gold and is unreadable at nav-link size. Charcoal clears 4.8:1. */
.site-footer {
  --bg:var(--gold);
  --heading:var(--on-accent);
  --body:var(--on-accent);
  --btn-bg:var(--cream);
  --btn-fg:var(--on-accent);
  /* <footer> isn't covered by the section rule, so it paints --bg itself. */
  background:var(--bg);
  color:var(--body);
  --footer-pill:#fff;
  text-align:center;
  /* Gold runs to the bottom edge; the copyright stays above the indicator. */
  padding-bottom:calc(clamp(38px,4.5vw,60px) + var(--safe-b));
}
.site-footer .wordmark { width:190px; height:auto; margin-bottom:26px; }
/* Each wordmark asks its own ground whether to invert, rather than the rule
   guessing: --logo-filter is none wherever the section kept its colour. */
.site-header img,
.notebook-header img,
.site-footer .wordmark { filter:var(--logo-filter); }
/* The header nav's hover: a pill fades and scales in behind the link while the
   link lifts. Kept in this sheet rather than motion.css so the document pages,
   which don't load that one, get it too. The pill is white so it reads on the
   gold footer, on both the landing <footer> and the document <section>. */
.site-footer nav a {
  position:relative;
  isolation:isolate;
  display:inline-flex; align-items:center; margin:0 14px 10px;
  font-size:.95rem; font-weight:600; text-decoration:none;
  transition:transform 180ms ease, color 180ms ease;
}
.site-footer nav a::before {
  content:"";
  position:absolute;
  inset:-8px -9px;
  z-index:-1;
  /* The download button's pill, so the footer's hover shape matches it. */
  border-radius:999px;
  background:var(--footer-pill, var(--gold));
  opacity:0;
  transform:scale(.92);
  transition:opacity 180ms ease, transform 180ms ease, box-shadow 180ms ease;
}
.site-footer nav a:focus-visible::before { opacity:1; transform:scale(1); }
@media (hover:hover) and (pointer:fine) {
  .site-footer nav a:hover { transform:translateY(-2px); }
  .site-footer nav a:hover::before {
    opacity:1; transform:scale(1); box-shadow:0 4px 12px rgb(var(--shadow-rgb) / 12%);
  }
}
.site-footer nav a:active { transform:scale(.97); box-shadow:none; }
@media (prefers-reduced-motion:reduce) {
  .site-footer nav a, .site-footer nav a::before { transition:none; }
  .site-footer nav a:hover, .site-footer nav a:active { transform:none; }
}
.site-footer .copyright { margin-top:20px; font-size:.85rem; }

@media (max-width:760px) {
  .site-footer nav a { min-height:44px; padding:8px 4px; font-size:1rem; }
  .site-footer .copyright { font-size:1rem; }
}

@media (max-width:440px) {
  .site-footer nav a { margin:0 10px 10px; }
}

@media (prefers-reduced-motion:reduce) {
  .badge { transition:none; }
  .badge:hover { transform:none; }
}

/* Scroll reveal ---------------------------------------------------------
   Scoped to .reveal-ready, which the script adds to <html> only when it can
   actually reveal things again — so no JS or reduced-motion leaves content
   plainly visible. Applied to section content, not the <section>: fading a
   full-bleed section would fade its background too. */
.reveal-ready .reveal {
  opacity:0; transform:translateY(22px);
  transition:opacity .7s ease, transform .7s ease;
  will-change:opacity, transform;
}
.reveal-ready .reveal.is-visible { opacity:1; transform:none; }
