/* ============================================================
   Essington Institute — site system (2026-09 redesign)
   Shared chrome and components for every page: frosted nav +
   full-screen menu, plates, cards, buttons, kicker, transitions,
   footer. Tokens come from tokens-*.css. Light theme only.
   ============================================================ */

:root {
  --paper: var(--tc-stock);
  --paper-deep: var(--tc-stock-deep);
  --paper-light: var(--tc-stock-input);
  --ink: var(--tc-ink);
  --ink-soft: var(--tc-ink-soft);
  --copper: var(--tc-copper);
  --copper-deep: var(--tc-copper-deep);
  --copper-light: var(--tc-copper-light);
  --cream: var(--tc-cream);
  --cream-soft: var(--tc-cream-soft);
  --rule: rgba(30, 43, 38, 0.14);
  --rule-cream: rgba(244, 240, 229, 0.18);

  --serif: var(--tc-serif);
  --sans: var(--tc-sans);
  --mark: var(--tc-mark);

  --t-body: 1.125rem;
  --t-lede: clamp(1.25rem, 1.6vw, 1.5rem);
  --t-h3: 1.75rem;
  --t-h2: clamp(2.4rem, 4.4vw, 3.8rem);
  --t-hero: clamp(2.6rem, 6vw, 5rem);
  --t-small: 0.9375rem;

  --gutter: var(--tc-page-gutter);
  --measure: 34em;
  --ease-out: var(--tc-ease-out);
}

*, *::before, *::after { box-sizing: border-box; }
/* scrollbar-gutter: the menu locks scroll with overflow:hidden; without a reserved
   gutter the classic (Windows/Linux) scrollbar vanishes, the viewport widens ~15px,
   and the hero canvas's ResizeObserver rebuilds the whole fleet mid-fade. */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
/* Body copy is the sans; the serif is for headings, the lockup and quotations. */
body { margin: 0; background: var(--paper); color: var(--ink); font-family: var(--sans); font-size: var(--t-body); line-height: 1.55; font-feature-settings: "pnum" 1; }
a { color: inherit; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
.tc-root { background: var(--paper); color: var(--ink); }
h1, h2, h3 { font-family: var(--serif); font-weight: 400; }
/* One margin reset for flow content, at element specificity (0,0,1). Components
   set their own spacing and win normally. This replaces `.plate p { margin: 0 }`,
   which sat at (0,1,1) and silently beat any single-class rule: every layer that
   wanted a paragraph margin inside a plate had to out-specify it with a `.plate`
   or page prefix, and forgetting to was a recurring spacing bug. Lists are left
   alone; news articles and the legal pages rely on their own list spacing. */
h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }

.wrap { padding-inline: var(--gutter); max-width: var(--tc-page-max); margin-inline: auto; }
.grid { display: grid; grid-template-columns: repeat(12, 1fr); column-gap: 1.5rem; }
.stack > * + * { margin-top: 1.5rem; }
/* Body text fills the container it sits in. A narrow measure is the job of a
   narrow container (a card, a grid column, a reading column such as
   .news-col), never of the text element itself: a paragraph that caps its own
   width leaves half its card empty. Headings keep their own max-width, which
   is a deliberate device. */
.copy { }
.lede { font-size: var(--t-lede); line-height: 1.4; }
.source { font-family: var(--sans); font-size: 0.8125rem; line-height: 1.45; color: var(--ink-soft); }
.kicker { font-family: var(--sans); font-size: var(--t-small); font-weight: 600; color: var(--copper); margin: 0 0 1.25rem; }
.kicker--star { display: inline-flex; align-items: center; gap: 0.6rem; }
.kicker__star { width: 14px; height: 14px; background: var(--copper); -webkit-mask: url('../assets/tilted-star.svg') center/contain no-repeat; mask: url('../assets/tilted-star.svg') center/contain no-repeat; }

/* ---- Buttons & links ---- */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem; font-family: var(--sans); font-weight: 600; font-size: var(--t-small);
  text-decoration: none; text-transform: none; letter-spacing: 0; line-height: 1.1; cursor: pointer;
  padding: 0.8em 1.25em; border-radius: var(--tc-radius-ui); border: 0;
  background: var(--ink); color: var(--cream); box-shadow: var(--tc-shadow-btn);
  transition: background 0.2s ease, color 0.2s ease, transform 0.2s var(--ease-out), box-shadow 0.2s ease;
}
.btn:hover { background: var(--copper); color: var(--cream); transform: translateY(-1px); }
.btn svg { width: 14px; height: 14px; flex: none; }
.btn--cream { background: var(--cream); color: var(--ink); }
.btn--cream:hover { background: var(--copper-light); color: var(--ink); }
.btn--ghost { background: rgba(244,240,229,0.6); color: var(--ink); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.5); box-shadow: none; }
.btn--ghost:hover { background: var(--ink); color: var(--cream); }
/* On the copper plate the default hover (copper) would vanish into the surface,
   and a translucent ghost would read as no button at all. */
.plate--copper .btn { background: var(--tc-on-accent); color: var(--cream); }
.plate--copper .btn:hover { background: var(--cream); color: var(--ink); }
.plate--copper .btn--ghost { background: var(--cream); color: var(--ink); border: 0; box-shadow: var(--tc-shadow-btn); }
.plate--copper .btn--ghost:hover { background: var(--tc-on-accent); color: var(--cream); }
.link { font-family: var(--sans); font-size: var(--t-small); font-weight: 600; text-decoration: none; border-bottom: 1.5px solid var(--copper); padding-bottom: 0.15em; }
.link:hover { border-color: currentColor; }

/* ---- Nav: full-width and transparent at the top of the page; once the reader
   scrolls it condenses into the floating frosted bar (as nif.fund). ---- */
.mast {
  position: fixed; top: 0; left: 50%; transform: translateX(-50%); z-index: 40;
  width: 100%; height: var(--tc-nav-h); padding: 0 var(--gutter);
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  border-radius: 0; background: rgba(255, 255, 255, 0);
  color: var(--ink);
  transition: width 0.55s var(--ease-out), height 0.55s var(--ease-out), top 0.55s var(--ease-out), padding 0.55s var(--ease-out),
              border-radius 0.55s var(--ease-out), background-color 0.4s ease, color 0.3s ease;
}
.scrolled .mast {
  top: 1rem; width: min(100% - 2rem, 67rem); height: 4.75rem; padding: 0 0.7rem; /* symmetric, so the centred lockup stays centred */
  border-radius: var(--tc-radius-nav); background: var(--tc-glass-bg);
  -webkit-backdrop-filter: var(--tc-glass-blur); backdrop-filter: var(--tc-glass-blur);
}
.scrolled .menu-toggle { padding-left: 0.8rem; }   /* the compact bar's inner inset, given to the toggle rather than the bar so the grid stays symmetric */
.menu-open .mast { background: var(--tc-glass-bg-ink); color: var(--cream); }
/* Over a dark surface ([data-dark] or an ink plate) the text, lockup and button flip
   to cream. Colour only; the tint never changes. Driven by js/chrome.js. */
.mast[data-on-dark="true"] { color: var(--cream); }
.mast[data-on-dark="true"] .btn { background: var(--cream); color: var(--ink); }
.mast[data-on-dark="true"] .btn:hover { background: var(--copper-light); }
.brand { display: inline-flex; align-items: center; gap: 0.65rem; text-decoration: none; justify-self: center; }
/* The brand lockup (assets/essington-lockup.svg) inlined so it takes currentColor.
   Inline SVG, not a CSS mask: a mask re-rasterises every frame while the bar
   animates and shimmers; a vector path stays crisp.
   In the nav: at the top of the page only the star shows; as the bar compacts the
   clip widens (the centred box grows both ways, so the star slides left) and the
   wordmark emerges from behind it. Star height = the button's height. The lockup's
   star occupies x 5–73 of the 490.65-unit viewBox and y 5–73 of 78.2. */
.brand { --lockup-h: 3.4rem; --lockup-w: calc(var(--lockup-h) * 490.65 / 78.2); --star-w: calc(var(--lockup-h) * 78 / 78.2); }
.brand__clip { display: block; height: var(--lockup-h); width: var(--star-w); overflow: hidden; transition: width 0.6s var(--ease-out); }
.brand__lockup { display: block; height: var(--lockup-h); width: var(--lockup-w); }
.brand__word, .brand__starpath { fill: currentColor; }
.brand__word { transform: translateX(-12%); opacity: 0; transition: transform 0.6s var(--ease-out), opacity 0.35s ease; }
.scrolled .brand__clip { width: var(--lockup-w); }
.scrolled .brand__word { transform: none; opacity: 1; transition-delay: 0.08s; }
/* Footer: the plain, full lockup. */
.site-foot .brand__lockup { height: 28px; width: auto; }
.site-foot .brand__word { transform: none; opacity: 1; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.mast__end { justify-self: end; }
.mast .btn { padding: 0.95em 1.4em; border-radius: var(--tc-radius-btn); box-shadow: none; font-size: 1rem; transition: background 0.3s ease, color 0.3s ease; }
.menu-open .mast .btn { background: var(--cream); color: var(--ink); }
.menu-toggle { display: inline-flex; align-items: center; gap: 1.25rem; background: none; border: 0; padding: 0.4rem 0; transition: padding 0.5s var(--ease-out); color: inherit; cursor: pointer; font-family: var(--sans); font-size: var(--t-small); font-weight: 600; }
.menu-toggle__lines { display: flex; flex-direction: column; justify-content: center; gap: 0.55rem; width: 2.25rem; height: 1.5rem; }
.menu-toggle__lines span { display: block; height: 2px; width: 100%; background: currentColor; transform-origin: center; transition: transform 0.25s ease; }
@media (hover: hover) { .menu-toggle:hover .menu-toggle__lines span { transform: scaleX(0.55); } }
.menu-open .menu-toggle__lines span:first-child { transform: translateY(calc(0.275rem + 1px)) rotate(45deg); }
.menu-open .menu-toggle__lines span:last-child { transform: translateY(calc(-0.275rem - 1px)) rotate(-45deg); }

.menu-overlay { position: fixed; inset: 0; z-index: 30; background: rgba(30, 43, 38, 0.96); color: var(--cream); display: flex; align-items: center; opacity: 0; visibility: hidden; transition: opacity 0.45s ease, visibility 0.45s ease; -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
.menu-open .menu-overlay { opacity: 1; visibility: visible; }
.menu-overlay .wrap { width: 100%; }
.menu-overlay .menu { list-style: none; margin: 0; padding: 0 0 0 8.333%; }
.menu-overlay .menu li { opacity: 0; transform: translateY(1.25rem); transition: opacity 0.2s ease, transform 0.2s ease; }
.menu-open .menu-overlay .menu li { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.7s var(--ease-out); }
.menu-open .menu-overlay .menu li:nth-child(1) { transition-delay: 0.10s; }
.menu-open .menu-overlay .menu li:nth-child(2) { transition-delay: 0.16s; }
.menu-open .menu-overlay .menu li:nth-child(3) { transition-delay: 0.22s; }
.menu-open .menu-overlay .menu li:nth-child(4) { transition-delay: 0.28s; }
.menu-open .menu-overlay .menu li:nth-child(5) { transition-delay: 0.34s; }
.menu-open .menu-overlay .menu li:nth-child(6) { transition-delay: 0.40s; }
.menu-overlay .menu a { display: inline-block; text-decoration: none; font-family: var(--serif); font-size: clamp(2.4rem, 5.5vw, 4.5rem); line-height: 1.05; letter-spacing: -0.01em; padding-block: 0.6rem; }
.menu-overlay .menu a:hover { color: var(--copper-light); }
.menu-overlay__foot { position: absolute; left: var(--gutter); right: var(--gutter); bottom: 2rem; margin: 0; font-family: var(--sans); font-size: 0.8125rem; color: var(--cream-soft); }

/* ---- Plates: full-width rounded surfaces, inset from the edge ---- */
.plate { margin: var(--tc-plate-gap); border-radius: var(--tc-radius-plate); padding-block: var(--tc-plate-pad-y); position: relative; overflow: hidden; }
.plate--deep { background: var(--paper-deep); }
.plate--light { background: var(--paper-light); }
.plate--ink { background: var(--ink); color: var(--cream); }
.plate--copper { background: var(--tc-accent-surface); color: var(--tc-on-accent); }
.plate--ink .source { color: var(--cream-soft); }
.plate--ink .kicker { color: var(--copper-light); }
/* The default kicker is copper, which disappears on the copper plate. */
.plate--copper .kicker { color: var(--tc-on-accent); }
/* No margin here: at (0,1,1) it beat every single-class heading rule, the same bug the
   paragraph reset above was moved to fix. The element reset already zeroes headings. */
.plate h1, .plate h2, .plate h3 { font-weight: 400; }
.plate h2 { font-size: var(--t-h2); line-height: 1.04; letter-spacing: -0.02em; text-wrap: balance; }
.plate h2 em { font-style: normal; color: var(--copper); }
.h2--lines { text-wrap: initial; }
.h2--lines > span { display: block; }

/* The first plate on a page starts below the floating nav rather than running
   up behind it, which is what the home page's hero does with its top padding.
   Every page-top element sets this the same way, from the one token. */
.plate.page-hero, .plate.news-main, .plate.register-page, .plate.legal { margin-top: var(--tc-nav-h); }
/* Page hero as a plate (inner pages): big serif title and lede. */
.page-hero { padding-top: var(--tc-plate-pad-y); }
.page-hero h1 { font-size: var(--t-hero); line-height: 1.02; letter-spacing: -0.015em; max-width: 14em; text-wrap: balance; }
.page-hero .lede { margin-top: 1.75rem; color: var(--ink-soft); }
.plate--ink.page-hero .lede { color: var(--cream-soft); }

/* One text edge per plate. A card insets its own contents by --tc-card-pad,
   so a section heading sitting on the plate gutter never lined up with the
   heading inside the card below it. The text container takes that inset
   instead, and the rows of cards pull back out to the gutter: everything that
   is text now shares one left edge, and card backgrounds sit just outside it.
   Phones are left alone, where the inset would only cost width. */
@media (min-width: 901px) {
  .plate > .wrap,
  .section__inner { padding-inline: calc(var(--gutter) + var(--tc-card-pad)); }
  .count-grid, .bench-grid, .about-cards, .about-areas, .about-isnot__cols,
  .about-vision__grid, .news-grid, .focus__cols, .pullquote, .endnotes-fold,
  .sv-board, .about-positions__panels, .serve-cards, .tl-list,
  .sv-places { margin-inline: calc(-1 * var(--tc-card-pad)); }
  /* Not the close plate's button row: it is not a row of cards, it is content
     inside a half-width column, so pulling it out only knocks it out of line
     with the paragraph directly above it. */
}

/* ---- Cards ---- */
.card {
  text-align: center; background: var(--paper-light); border-radius: var(--tc-radius-card); padding: var(--tc-card-pad);
  box-shadow: var(--tc-shadow-card); border: 1px solid rgba(255,255,255,0.6);
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s var(--ease-out);
}
.card h3 { font-size: var(--t-h3); line-height: 1.15; letter-spacing: -0.01em; margin: 0; font-weight: 400; min-height: 2.3em; /* reserve two lines so every description starts at the same height */ }
.card p { margin: 0.9rem auto 0; font-family: var(--sans); font-size: 1rem; line-height: 1.55; color: var(--ink-soft); transition: color 0.3s ease; }
.card__icon { width: 40px; height: 40px; color: var(--copper); margin: 0 auto 1.5rem; transition: color 0.3s ease; }
.card__icon svg { width: 100%; height: 100%; display: block; }
@media (hover: hover) {
  /* Stays on the light stock: lifts, deepens the shadow, and picks up a copper
     hairline; the icon presses to copper-deep. */
  .card--hover:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--copper) 55%, transparent); box-shadow: var(--tc-shadow-card-hover); }
  .card--hover:hover .card__icon { color: var(--copper-deep); }
  .card--hover:hover p { color: var(--ink); }
}
/* A card on a light plate would be the plate's own colour, told apart only by its shadow.
   It takes the paper one step down instead, like every other card-like surface there
   (the legal contents box, the About columns and lists). */
.plate--light .card { background: var(--paper); }
.card--left { text-align: left; }
.card--left p { margin-inline: 0; }

/* ---- Swapper: a tab row with a pill that slides to the selected tab, and
   one panel shown at a time. Driven by js/swapper.js; used by /serve and
   /about. Without JS every tab shows and the first panel is open. ---- */
.swap {
  position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0.25rem;
  padding: 0.35rem; border-radius: 999px; background: var(--paper-deep);
}
.swap__indicator {
  position: absolute; top: 0.35rem; bottom: 0.35rem; left: 0; width: 0; border-radius: 999px; background: var(--ink);
  box-shadow: 0 4px 12px -6px rgba(30,43,38,0.5); pointer-events: none;
  transition: transform 0.45s var(--ease-out), width 0.45s var(--ease-out);
}
.swap__btn {
  position: relative; z-index: 1; font-family: var(--sans); font-size: var(--t-small); font-weight: 600;
  color: var(--ink-soft); border: 0; border-radius: 999px; padding: 0.7rem 0.5rem; background: transparent;
  cursor: pointer; transition: color 0.25s;
}
.swap__btn:hover { color: var(--ink); }
.swap__btn[aria-selected="true"] { color: var(--cream); }
/* Before the indicator exists (no JS), the selected tab carries the fill. */
.swap:not(.has-indicator) .swap__btn[aria-selected="true"] { background: var(--ink); }
.swap__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* On ink, the row sits on a lighter wash and the pill inverts to cream. */
.plate--ink .swap { background: rgba(244,240,229,0.08); }
.plate--ink .swap__indicator { background: var(--cream); box-shadow: none; }
.plate--ink .swap__btn { color: var(--cream-soft); }
.plate--ink .swap__btn:hover { color: var(--cream); }
.plate--ink .swap__btn[aria-selected="true"] { color: var(--ink); }
.plate--ink .swap:not(.has-indicator) .swap__btn[aria-selected="true"] { background: var(--cream); }
.plate--ink .swap__btn:focus-visible { outline-color: var(--cream); }

[data-swap-panel][hidden] { display: none; }
@keyframes swap-enter { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
[data-swap-panel].is-entering { animation: swap-enter 0.45s var(--ease-out) both; }
/* Where the tab already names the panel, the heading is for screen readers
   and for readers without JS. */
[data-swap-panels].is-swapped [data-swap-panel] > h3 {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* ---- Footer ---- */
.site-foot { padding: 2rem var(--gutter) 3rem; font-family: var(--sans); font-size: 0.8125rem; color: var(--ink-soft); }
.site-foot .wrap { display: flex; justify-content: space-between; align-items: center; gap: 2rem; flex-wrap: wrap; padding: 0; }
/* The page links sit beside the lockup; the legal line takes its own row. */
.site-foot__nav { display: flex; gap: 1.25rem 1.75rem; flex-wrap: wrap; }
.site-foot__nav a { text-decoration: none; font-weight: 600; color: var(--ink); }
.site-foot__nav a:hover { text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
.site-foot .wrap > p { flex-basis: 100%; }
.site-foot .brand { color: var(--ink); }
.site-foot p { margin: 0; }
/* The legal line: the pipes are drawn here rather than typed, so on phones the links can
   drop to their own row without a divider left hanging at the end of a line. */
.site-foot__nowrap { white-space: nowrap; }
.site-foot__legal a { white-space: nowrap; }
.site-foot__legal a::before { content: "|" / ""; margin: 0 0.6em; color: var(--ink-soft); display: inline-block; text-decoration: none; }
@media (max-width: 640px) {
  .site-foot__legal { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; margin-top: 0.6rem; }
  .site-foot__legal a::before { content: none; }
}

/* ---- Section transitions (JS-only; no-JS readers see everything) ---- */
.js [data-scroll] [data-in] { opacity: 0; transform: translateY(1.5rem); transition: opacity 0.7s ease, transform 0.9s var(--ease-out); }
.js [data-scroll].inview [data-in] { opacity: 1; transform: none; }
.js [data-scroll].inview [data-in]:nth-child(2) { transition-delay: 0.08s; }
.js [data-scroll].inview [data-in]:nth-child(3) { transition-delay: 0.16s; }
.js [data-scroll].inview [data-in]:nth-child(4) { transition-delay: 0.24s; }
.js [data-split] .w { display: inline-block; overflow: hidden; vertical-align: bottom; margin-bottom: -0.18em; padding-bottom: 0.18em; }
.js [data-split] .w > span { display: inline-block; transform: translateY(110%); transition: transform 0.9s var(--ease-out); transition-delay: calc(var(--i) * 40ms); }
.js [data-scroll].inview [data-split] .w > span { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-scroll] [data-in], .js [data-split] .w > span { opacity: 1; transform: none; transition: none; }
  .mast, .menu-overlay, .menu-overlay .menu li, .menu-toggle__lines span, .card, .btn, .brand__clip, .brand__word { transition: none; }
  .swap__indicator, .swap__btn { transition: none; }
  [data-swap-panel].is-entering { animation: none; }
}

/* ---- Responsive ---- */
@media (max-width: 900px) {
  .grid { display: block; }
  .menu-toggle__label { display: none; }
  .menu-overlay .menu { padding-left: 0; }
  .menu-overlay__foot { bottom: 1.5rem; }
}
@media (max-width: 900px) {
  .swap { grid-auto-flow: row; grid-auto-columns: auto; border-radius: var(--tc-radius-card); gap: 0.35rem; }
  .swap__indicator { display: none; }
  .swap .swap__btn[aria-selected="true"] { background: var(--ink); }
  .plate--ink .swap .swap__btn[aria-selected="true"] { background: var(--cream); }
}
@media (max-width: 640px) {
  :root { --tc-nav-h: 4.25rem; }
  .scrolled .mast { top: 0.75rem; height: 3.75rem; width: calc(100% - 1.5rem); padding: 0 0.5rem; border-radius: 12px; }
  .scrolled .menu-toggle { padding-left: 0.5rem; }
  .mast .btn { padding: 0.75em 1em; font-size: 0.875rem; }
  .plate { margin: 0.5rem; }
}
@media (max-width: 560px) {
  .brand { --lockup-h: 2.4rem; }
  /* Phones: no button in the bar (it lives in the menu); the brand sits at the right edge,
     star alone at the top, full lockup once scrolled. */
  .mast { grid-template-columns: 1fr auto; }
  .mast__end { display: none; }
  .brand { order: -1; justify-self: start; }   /* brand left (star stays put, wordmark unfolds rightward) */
  .menu-toggle { justify-self: end; }         /* hamburger right */
  .mast .btn { font-size: 0.8125rem; white-space: nowrap; }
}
