/* ============================================================
   Doab Construction — light
   Off-white paper ground, no ambient, no backdrop. The colour
   lives in the logo and the three widgets; everything else is
   paper, ink and a hairline.
   Brand: gold #CBA739 · teal #6DDCD2
   ============================================================ */

/* ---------- typefaces ----------
   Both are self-hosted variable fonts, subset to what this site sets,
   so there is no third-party request and no flash of fallback text.

   "DotoNum" is Doto restricted by unicode-range to U+0030-0039. Listing
   it first in the stack means every digit anywhere on the site renders
   in Doto while every letter falls through to Inter — no markup needed.
   "Doto" is the same file unrestricted, applied only to elements that
   are wholly a figure, so the colon in 9:41 and the degree in 15° are
   dot-matrix too rather than stranded in Inter.                       */
@font-face{
  font-family:"Inter";
  src:url("fonts/inter.woff2?v=b9587f87") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
}
/* Pinned to wght 800, and declared 100-900 so ANY requested weight
   still renders at 800. A dot-matrix figure carries less ink than a
   solid letter, so at text sizes the lighter cuts read as damaged
   type beside Inter; 800 is the first weight that holds its own. */
@font-face{
  font-family:"DotoNum";
  src:url("fonts/doto-text.woff2?v=438967a4") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
  unicode-range:U+0030-0039;
}
@font-face{
  font-family:"Doto";
  src:url("fonts/doto.woff2?v=c5e41c85") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
}

:root{
  --gold:#CBA739;
  --gold-dp:#8A6E1E;      /* gold that holds up as text on paper */
  --teal:#6DDCD2;
  --teal-dp:#2E8A82;      /* teal that holds up as text on paper */
  /* The logo turquoise is only 1.47:1 on this paper — unreadable as
     text. This is the same hue taken down until it clears AA for body
     copy (4.84:1), which a dot-matrix figure needs even more than solid
     type because the lattice carries less ink than it appears to. */
  --teal-num:#27766F;

  --paper:#F3F3F1;        /* the ground */
  --card:#FFFFFF;
  --card-2:#EDEDEA;

  --ink:#191A1C;
  --ink-2:rgba(25,26,28,.64);
  /* Secondary text. .44 measured 2.78:1 once the glass plinth lifted the
     background — these captions are content, not decoration, so this is
     the alpha that actually clears AA (4.79:1) rather than one that
     merely looks quiet. Nudged again once the ground gained colour: the
     gold corner is the darkest surface on the site and left only 4.53:1
     at .62, which passes but with no room. */
  --ink-3:rgba(25,26,28,.66);
  --ink-4:rgba(25,26,28,.26);

  --line:rgba(25,26,28,.10);
  --line-2:rgba(25,26,28,.18);

  --shadow-sm:0 1px 2px rgba(25,26,28,.05);

  --r-lg:20px;
  --r-md:14px;
  --r-pill:999px;
  --maxw:940px;

  /* DotoNum first: it only claims the digits, everything else is Inter */
  --sans:"DotoNum","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",
         Roboto,system-ui,sans-serif;
  /* for elements that are wholly a figure — punctuation included */
  --figure:"Doto","DotoNum","Inter",system-ui,sans-serif;
}

/* ============================================================
   Liquid glass — the material system
   Glass is only glass if there is something behind it. The ground
   below carries a whisper of the logo's gold and turquoise: on its
   own the page still reads off-white, but the colour is there for
   the glass edges to catch, which is what stops a translucent panel
   looking like flat white paint.

   COST: backdrop-filter is the single most expensive thing on this
   page. It is spent only on surfaces you can count — the nav, the
   buttons, the two detail panels, the statistics plinth. Repeated
   elements (21 project tiles, 12 gallery frames) get the rim, the
   shadow and the sheen, which cost nothing, and no filter at all.
   ============================================================ */
:root{
  /* Thin tints on purpose: the panel has to let the ground through or
     there is nothing to refract. The blur and the saturation boost are
     what turn what shows through into colour rather than mud. */
  --glass-blur:34px;
  --glass-sat:200%;
  --glass-tint:rgba(255,255,255,.30);
  --glass-tint-thin:rgba(255,255,255,.20);
  --glass-tint-thick:rgba(255,255,255,.40);
  --glass-rim:rgba(255,255,255,.98);     /* light landing on the top edge */
  --glass-rim-low:rgba(255,255,255,.48); /* bounce off the bottom edge   */
  --glass-edge:rgba(255,255,255,.58);
}

/* The ground: an opal wash in the logo's two colours. This is what the
   glass has to bend — a panel over flat paper is just a white rectangle,
   which is why the first, subtler version of this read as nothing at all.
   Luminance stays high everywhere (the lightest tint still measures well
   above 0.6), so near-black text keeps its contrast across the whole
   field. Fixed, so it does not slide against the content while scrolling. */
body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(125% 90% at -4% -8%,rgba(109,220,210,.62),rgba(109,220,210,0) 58%),
    radial-gradient(115% 85% at 104% -4%,rgba(238,203,118,.66),rgba(238,203,118,0) 60%),
    radial-gradient(120% 95% at 106% 104%,rgba(46,138,130,.48),rgba(46,138,130,0) 62%),
    radial-gradient(115% 90% at -6% 106%,rgba(203,167,57,.46),rgba(203,167,57,0) 62%),
    radial-gradient(80% 60% at 50% 45%,rgba(255,255,255,.55),rgba(255,255,255,0) 70%),
    linear-gradient(162deg,#FBFBF9 0%,#F2F5F3 46%,#F9F4EA 100%);
}
/* a dither over the bloom — wide, shallow gradients band badly without it */
body::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.7;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.045'/%3E%3C/svg%3E");
  background-size:160px 160px;
}

/* ---------- the material ---------- */
/* The full recipe. Every line is doing one job:
   the gradient body gives the pane its own sheen; the filter bends and
   re-saturates the ground; the four inset rims are light landing on a
   solid edge; the inner glow is light scattering inside the thickness
   of the glass; the two outer shadows are contact and depth. */
.lg{
  position:relative;isolation:isolate;
  background:linear-gradient(152deg,
    rgba(255,255,255,.46) 0%,rgba(255,255,255,.16) 48%,rgba(255,255,255,.38) 100%);
  -webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat)) brightness(1.06);
          backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat)) brightness(1.06);
  border:1px solid var(--glass-edge);
  box-shadow:
    inset 0 1px 0 var(--glass-rim),
    inset 0 -1px 0 var(--glass-rim-low),
    inset 1px 0 0 rgba(255,255,255,.42),
    inset -1px 0 0 rgba(255,255,255,.42),
    inset 0 0 28px rgba(255,255,255,.26),
    0 1px 2px rgba(25,26,28,.07),
    0 26px 60px -28px rgba(25,26,28,.46);
}

/* The refractive edge — a hairline that picks up turquoise on one side
   and gold on the other, the way a real bevel splits light. Drawn as a
   masked gradient ring so it can carry colour a border cannot. */
.lg-edge{position:relative}
.lg-edge::before{
  content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;
  padding:1px;pointer-events:none;
  background:linear-gradient(152deg,
    rgba(109,220,210,.95) 0%,rgba(255,255,255,.65) 34%,
    rgba(255,255,255,.25) 58%,rgba(203,167,57,.90) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
/* §12: a bigger surface should read as thicker glass */
.lg-thick{
  --glass-blur:46px;
  background:linear-gradient(152deg,
    rgba(255,255,255,.56) 0%,rgba(255,255,255,.24) 48%,rgba(255,255,255,.46) 100%);
  box-shadow:
    inset 0 1px 0 var(--glass-rim),
    inset 0 -1px 0 var(--glass-rim-low),
    0 1px 2px rgba(25,26,28,.06),
    0 30px 64px -30px rgba(25,26,28,.42);
}
.lg-thin{
  --glass-blur:20px;
  background:linear-gradient(152deg,
    rgba(255,255,255,.34) 0%,rgba(255,255,255,.12) 48%,rgba(255,255,255,.28) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.75),
    0 1px 2px rgba(25,26,28,.04),
    0 8px 20px -14px rgba(25,26,28,.30);
}

/* The surfaces that catch the moving light. Each pseudo-element is
   absolutely positioned, so it drops out of its parent's flex or grid
   flow rather than becoming a stray child. */
.btn::after,.pshot::after,.gempty::after,.badges::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(14em 14em at var(--mx,50%) var(--my,0%),
    rgba(255,255,255,.50),rgba(255,255,255,.10) 44%,rgba(255,255,255,0) 70%);
  opacity:0;transition:opacity .34s cubic-bezier(.32,.72,0,1);
}
.btn:hover::after,.btn:focus-visible::after,
.pcell:hover .pshot::after,
.gempty:hover::after,.badges:hover::after{opacity:1}
.badges{position:relative}
.gempty{position:relative}

/* the widget tiles read as glass panes rather than flat gradient cards */
.widget{
  border:1px solid rgba(255,255,255,.16);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.34),
    inset 0 -1px 0 rgba(255,255,255,.10),
    0 1px 2px rgba(25,26,28,.06),
    0 26px 54px -26px rgba(25,26,28,.46);
}

/* ---------- materialise (§12: blur and scale resolve together) ----------
   Only applied once glass.js has marked an element, so a panel is never
   left invisible if the script fails to run. */
@media(prefers-reduced-motion:no-preference){
  .lg-rise{opacity:0;transform:translateY(10px) scale(.985);filter:blur(6px)}
  .lg-rise.lg-in{
    opacity:1;transform:none;filter:blur(0);
    transition:opacity .5s cubic-bezier(.32,.72,0,1) var(--rise-delay,0ms),
               transform .62s cubic-bezier(.32,.72,0,1) var(--rise-delay,0ms),
               filter .56s cubic-bezier(.32,.72,0,1) var(--rise-delay,0ms);
  }
}

/* The refractive edge, applied to the surfaces whose ::before is free.
   .loctable is a table and cannot carry a reliable pseudo-element ring,
   so it keeps the plain bright rim instead. */
.badges::before,.gempty::before,.pshot::before,.btn::before{
  content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;
  padding:1px;pointer-events:none;
  background:linear-gradient(152deg,
    rgba(109,220,210,.95) 0%,rgba(255,255,255,.70) 32%,
    rgba(255,255,255,.22) 56%,rgba(203,167,57,.92) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:.85;transition:opacity .3s ease;
}
.pcell:hover .pshot::before,.btn:hover::before{opacity:1}
.pshot{position:relative}

/* The refractive ring goes on ::after — ::before is already the gold
   hairline above the nav on the project pages. */
.mainnav::after{
  content:"";position:absolute;inset:0;z-index:3;border-radius:inherit;
  padding:1px;pointer-events:none;
  background:linear-gradient(176deg,
    rgba(109,220,210,.95) 0%,rgba(255,255,255,.72) 38%,
    rgba(255,255,255,.30) 62%,rgba(203,167,57,.88) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}

/* the widget tiles get the same bright bevel so they read as one family */
.widget{
  border:1px solid rgba(255,255,255,.30);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.50),
    inset 0 -1px 0 rgba(255,255,255,.16),
    inset 0 0 30px rgba(255,255,255,.10),
    0 1px 2px rgba(25,26,28,.07),
    0 30px 62px -26px rgba(25,26,28,.50);
}

/* ---------- light moving across the surface ----------
   The sheen follows the pointer via --mx/--my, set in glass.js.
   Costs nothing: it is a gradient on a pseudo-element, no filter. */
.sheen{position:relative}
.sheen::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(14em 14em at var(--mx,50%) var(--my,0%),
    rgba(255,255,255,.55),rgba(255,255,255,.12) 42%,rgba(255,255,255,0) 68%);
  opacity:0;transition:opacity .34s cubic-bezier(.32,.72,0,1);
}
.sheen:hover::after,.sheen:focus-visible::after{opacity:1}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  min-height:100vh;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--sans);
  font-size:17px;
  line-height:1.47059;
  letter-spacing:-.022em;
  font-optical-sizing:auto;   /* Inter carries an opsz axis — let it work */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}

/* Both faces declare font-weight:100 900, so ordinary `font-weight`
   drives the wght axis directly. Never set font-variation-settings on
   an ancestor: it inherits as a literal string and would pin every
   descendant's weight, silently killing bold. */

.page{position:relative;max-width:var(--maxw);margin:0 auto;padding:0 20px 56px}
@media(max-width:600px){.page{padding:0 16px 44px}}

/* The landing page is deliberately sparse. On a screen with room to
   spare, sit the whole composition in the middle of the viewport
   rather than letting it hang off the top with dead space beneath. */
@media(min-height:860px){
  .page-center{
    min-height:100vh;display:flex;flex-direction:column;justify-content:center;
    padding-top:24px;
  }
  .page-center .masthead{padding-top:0}
}

/* ---------- the panel ---------- */
.glass{
  position:relative;
  background:var(--card);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);
}

/* ---------- header ---------- */
.masthead{padding:44px 0 26px;text-align:center}
.logo{display:inline-block;width:min(230px,58vw);height:auto}
.tagline{
  margin:18px auto 0;max-width:40ch;color:var(--ink-2);
  font-size:13px;letter-spacing:-.005em;line-height:1.55;
}
.tagline b{color:var(--gold-dp);font-weight:600;letter-spacing:.04em}
.masthead::after{
  content:"";display:block;width:72px;height:1px;margin:22px auto 0;
  background:linear-gradient(90deg,rgba(203,167,57,0),rgba(203,167,57,.75),rgba(203,167,57,0));
}

/* ============================================================
   Nav — Dynamic Island
   One continuous dark capsule rather than four separate pills. A
   single lit pill travels between the items; it follows the pointer
   on hover and settles on the current page when the pointer leaves,
   so the chrome is one object that changes shape rather than four
   objects that light up.
   ============================================================ */
.mainnav{
  position:relative;isolation:isolate;
  display:flex;justify-content:center;align-items:stretch;gap:2px;
  width:max-content;max-width:calc(100% - 8px);margin:0 auto;
  /* Wider at the ends than top-to-bottom on purpose: the first and last
     pill would otherwise sit inside the capsule's own rounded cap with
     no visible gap, which reads as the end item being misaligned. */
  padding:5px 9px;border-radius:var(--r-pill);
  background:linear-gradient(152deg,
    rgba(255,255,255,.54) 0%,rgba(255,255,255,.20) 48%,rgba(255,255,255,.44) 100%);
  -webkit-backdrop-filter:blur(30px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(30px) saturate(200%) brightness(1.06);
  border:1px solid var(--glass-edge);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.48),
    inset 1px 0 0 rgba(255,255,255,.42),
    inset -1px 0 0 rgba(255,255,255,.42),
    inset 0 0 24px rgba(255,255,255,.26),
    0 1px 2px rgba(25,26,28,.06),
    0 20px 44px -22px rgba(25,26,28,.40);
}

/* the travelling pill, injected by nav.js and driven from JS */
.nav-pill{
  position:absolute;top:5px;left:0;z-index:0;
  height:calc(100% - 10px);border-radius:var(--r-pill);
  background:linear-gradient(152deg,
    rgba(255,255,255,.90) 0%,rgba(255,255,255,.52) 50%,rgba(255,255,255,.78) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,1),
    inset 0 -1px 0 rgba(255,255,255,.60),
    inset 0 0 14px rgba(255,255,255,.40),
    0 1px 3px rgba(25,26,28,.10);
  opacity:0;pointer-events:none;
  /* critically damped, response ≈0.42s — Apple's "move/reposition" spring.
     A CSS transform transition retargets from its current computed value,
     so grabbing it mid-flight does not jump. */
  transition:transform .42s cubic-bezier(.32,.72,0,1),
             width     .42s cubic-bezier(.32,.72,0,1),
             opacity   .22s ease;
}
.mainnav.pill-ready .nav-pill{opacity:1}
/* Gold at low alpha over near-black always resolves to olive, so the
   selected pill is near-solid and the label under it flips to dark
   ink. nav.js marks that label, since the pill moves on hover. */
.nav-pill.is-gold{
  background:linear-gradient(152deg,
    rgba(250,236,190,.94) 0%,rgba(226,192,104,.88) 50%,rgba(206,170,74,.92) 100%);
  -webkit-backdrop-filter:blur(10px) saturate(190%);
          backdrop-filter:blur(10px) saturate(190%);
  box-shadow:
    inset 0 1px 0 rgba(255,252,240,1),
    inset 0 -1px 0 rgba(255,244,208,.55),
    inset 0 0 16px rgba(255,248,224,.45),
    0 1px 3px rgba(138,110,30,.28),
    0 6px 14px -8px rgba(138,110,30,.40);
}

.navbtn{
  position:relative;z-index:1;
  display:flex;align-items:center;justify-content:center;
  min-height:34px;padding:8px 17px;
  border-radius:var(--r-pill);
  font-size:13px;font-weight:500;letter-spacing:-.004em;white-space:nowrap;
  text-decoration:none;color:var(--ink-2);
  background:none;border:0;box-shadow:none;
  transition:color .22s ease;
}
.navbtn:hover,.navbtn:focus-visible{color:var(--ink)}
.navbtn[aria-current="page"]{color:var(--ink);font-weight:600;background:none;border:0}
/* whichever label the gold pill is currently sitting under */
.navbtn.on-gold,.navbtn.on-gold:hover{color:#2E2406}
.mainnav:focus-within .navbtn:focus-visible{outline:2px solid var(--teal-dp);outline-offset:2px}

/* Before nav.js runs — and if it never does — the current page still
   reads as selected. The pill is an enhancement, not the mechanism. */
.mainnav:not(.pill-ready) .navbtn[aria-current="page"]{
  background:linear-gradient(152deg,rgba(250,236,190,.94),rgba(206,170,74,.92));
  box-shadow:inset 0 1px 0 rgba(255,252,240,1);
  color:#2E2406;
}

@media(max-width:430px){
  .mainnav{gap:0;padding:4px}
  .navbtn{padding:8px 12px;font-size:12.5px}
}

/* ============================================================
   Widgets — gradient cards, dot-matrix figures
   The card carries its own aurora mesh rather than refracting a
   bloom behind it, so the colour survives at any size. Figures are
   filled with a dot lattice via background-clip:text, which is the
   signature of the reference set.
   ============================================================ */
/* A step smaller than they were: narrower measure and a shorter body,
   with every figure and label scaled by the same ~0.87 so the three
   cards keep their internal proportions rather than just squashing. */
.widgets{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;
  width:100%;max-width:800px;margin:34px auto 0}
@media(max-width:820px){
  .widgets{grid-template-columns:1fr 1fr}
  .w-sun{grid-column:1/-1}
}
@media(max-width:560px){
  .widgets{grid-template-columns:1fr}
  .w-sun{grid-column:auto}
}

.widget{
  position:relative;overflow:hidden;isolation:isolate;
  padding:18px 18px 15px;min-height:212px;display:flex;flex-direction:column;
  border-radius:30px;border:0;
  box-shadow:
    0 1px 2px rgba(25,26,28,.06),
    0 22px 46px -22px rgba(25,26,28,.42);
  color:#fff;
}
.widget > *{position:relative;z-index:2}

/* the mesh itself */
.widget::before{
  content:"";position:absolute;inset:0;z-index:0;border-radius:inherit;
  background:var(--mesh);
  transition:background 1.1s cubic-bezier(.32,.08,.24,1);
}
/* a light source top-left, plus grain so the gradient cannot band */
.widget::after{
  content:"";position:absolute;inset:0;z-index:1;border-radius:inherit;pointer-events:none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E"),
    radial-gradient(96% 58% at 14% -10%,rgba(255,255,255,.30),rgba(255,255,255,0) 62%);
  background-size:140px 140px,auto;
  background-repeat:repeat,no-repeat;
}

.w-clock{--mesh:
  radial-gradient(64% 72% at 18% 16%,#7FE6DB 0%,rgba(127,230,219,0) 62%),
  radial-gradient(70% 64% at 88% 24%,#2E8A82 0%,rgba(46,138,130,0) 64%),
  radial-gradient(90% 80% at 44% 108%,#06333E 0%,rgba(6,51,62,0) 72%),
  linear-gradient(158deg,#4ACFC2 0%,#0E5A6A 62%,#06323D 100%)}

/* Every card runs light at the top and deep at the bottom, so the big
   dot-matrix figure always lands on the dark end and always reads.
   The sun card is deepened at the foot for exactly that reason. */
.w-sun{--mesh:
  radial-gradient(62% 70% at 18% 14%,#FFD98A 0%,rgba(255,217,138,0) 60%),
  radial-gradient(72% 66% at 90% 26%,#E0982B 0%,rgba(224,152,43,0) 64%),
  radial-gradient(94% 86% at 46% 102%,#241102 0%,rgba(36,17,2,0) 78%),
  linear-gradient(158deg,#F5BE49 0%,#7A4D0D 52%,#221305 100%)}

.w-wx{--mesh:
  radial-gradient(64% 70% at 18% 16%,#A9BDD4 0%,rgba(169,189,212,0) 60%),
  radial-gradient(70% 64% at 88% 26%,#4E6780 0%,rgba(78,103,128,0) 64%),
  radial-gradient(90% 80% at 46% 108%,#12202E 0%,rgba(18,32,46,0) 72%),
  linear-gradient(158deg,#5E7B97 0%,#243646 46%,#101922 100%)}

.wx-clear-day{--mesh:
  radial-gradient(64% 70% at 18% 14%,#A8DCFF 0%,rgba(168,220,255,0) 60%),
  radial-gradient(72% 64% at 90% 26%,#1E86DC 0%,rgba(30,134,220,0) 64%),
  radial-gradient(92% 82% at 46% 110%,#04203C 0%,rgba(4,32,60,0) 72%),
  linear-gradient(158deg,#3F9EE2 0%,#0E4B7A 46%,#05223A 100%)}
.wx-clear-night{--mesh:
  radial-gradient(64% 70% at 18% 14%,#8E9BE8 0%,rgba(142,155,232,0) 60%),
  radial-gradient(72% 64% at 90% 26%,#2F3C9E 0%,rgba(47,60,158,0) 64%),
  radial-gradient(92% 82% at 46% 110%,#06081C 0%,rgba(6,8,28,0) 72%),
  linear-gradient(158deg,#3E49AC 0%,#161C52 46%,#07091D 100%)}
.wx-cloud{--mesh:
  radial-gradient(64% 70% at 18% 16%,#C3CEDA 0%,rgba(195,206,218,0) 60%),
  radial-gradient(70% 64% at 88% 26%,#5C748D 0%,rgba(92,116,141,0) 64%),
  radial-gradient(90% 80% at 46% 108%,#141E28 0%,rgba(20,30,40,0) 72%),
  linear-gradient(158deg,#6A8299 0%,#2B3D4E 46%,#131C25 100%)}
.wx-rain{--mesh:
  radial-gradient(64% 70% at 18% 14%,#93D2F2 0%,rgba(147,210,242,0) 60%),
  radial-gradient(72% 64% at 90% 26%,#1B6FA8 0%,rgba(27,111,168,0) 64%),
  radial-gradient(92% 82% at 46% 110%,#04222F 0%,rgba(4,34,47,0) 72%),
  linear-gradient(158deg,#3388B4 0%,#0C3E5C 46%,#051A26 100%)}
.wx-snow{--mesh:
  radial-gradient(64% 70% at 18% 16%,#DCE6EF 0%,rgba(220,230,239,0) 60%),
  radial-gradient(70% 64% at 88% 26%,#7A8FA4 0%,rgba(122,143,164,0) 64%),
  radial-gradient(90% 80% at 46% 108%,#1B242D 0%,rgba(27,36,45,0) 72%),
  linear-gradient(158deg,#889CAF 0%,#374651 46%,#161E25 100%)}
.wx-fog{--mesh:
  radial-gradient(64% 70% at 18% 16%,#CFD4DA 0%,rgba(207,212,218,0) 60%),
  radial-gradient(70% 64% at 88% 26%,#6B7580 0%,rgba(107,117,128,0) 64%),
  radial-gradient(90% 80% at 46% 108%,#181C21 0%,rgba(24,28,33,0) 72%),
  linear-gradient(158deg,#7A828B 0%,#31373E 46%,#14171B 100%)}
.wx-storm{--mesh:
  radial-gradient(64% 70% at 18% 14%,#B7A8E6 0%,rgba(183,168,230,0) 60%),
  radial-gradient(72% 64% at 90% 26%,#57459B 0%,rgba(87,69,155,0) 64%),
  radial-gradient(92% 82% at 46% 110%,#0C0818 0%,rgba(12,8,24,0) 72%),
  linear-gradient(158deg,#5D4CA6 0%,#251C4B 46%,#0B0818 100%)}

/* ---------- display figures ----------
   The dot matrix is the typeface now, not a background trick clipped to
   the glyphs, so the figures are real text at any size with no
   background-clip dependency and nothing to fall back from. */
.fig{
  font-family:var(--figure);
  font-variation-settings:"ROND" 0;
  font-variant-numeric:tabular-nums;
  font-weight:700;
}

.w-head{
  display:flex;align-items:center;gap:7px;
  font-size:12px;font-weight:500;letter-spacing:-.01em;color:rgba(255,255,255,.8);
}
.w-head svg{width:13px;height:13px;flex:none;opacity:.85}
.w-body{flex:1;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:10px 0}
.w-foot{
  font-size:11.5px;color:rgba(255,255,255,.7);text-align:center;
  border-top:1px solid rgba(255,255,255,.2);padding-top:10px;letter-spacing:-.008em;
}

.clockface{width:min(100px,34vw);aspect-ratio:1;display:block}
.digital{margin-top:12px;font-size:33px;letter-spacing:.01em;
  font-variant-numeric:tabular-nums;line-height:1}
.digital .ampm{font-size:.38em;font-weight:600;letter-spacing:.01em;margin-left:.3em;
  color:rgba(255,255,255,.75);-webkit-text-fill-color:rgba(255,255,255,.75);
  background:none;font-variant-numeric:normal}

.temp{font-size:45px;letter-spacing:.005em;line-height:1;
  font-variant-numeric:tabular-nums;margin:10px 0 4px}
/* the degree mark is too small to hold a lattice — keep it solid */
.temp .deg{color:#fff;font-family:"Inter",system-ui,sans-serif;
  font-weight:500;font-size:.5em;vertical-align:.24em;margin-left:.04em}
.cond{font-size:14px;color:rgba(255,255,255,.88);font-weight:400;letter-spacing:-.016em}
.hilo{display:flex;gap:16px;margin-top:10px;font-size:13.5px;
  font-variant-numeric:tabular-nums;color:rgba(255,255,255,.72);letter-spacing:-.016em}
.hilo b{color:#fff;font-weight:600}
.wx-icon{width:40px;height:40px}
.wx-rows{display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;width:100%;font-size:12px;text-align:left}
.wx-rows b{display:block;color:rgba(255,255,255,.56);font-weight:500;font-size:10.5px;letter-spacing:.012em}
.wx-rows span{color:rgba(255,255,255,.96)}

.sunarc{width:100%;max-width:162px;height:auto;display:block;margin:0 auto}
.suntime{margin-top:9px;font-size:33px;letter-spacing:.01em;line-height:1;
  font-variant-numeric:tabular-nums}
.suntime .ampm{font-size:.38em;font-weight:600;margin-left:.3em;letter-spacing:.01em;
  color:rgba(255,255,255,.75);-webkit-text-fill-color:rgba(255,255,255,.75);
  background:none;font-variant-numeric:normal}
.sunlabel{font-size:11px;font-weight:500;color:rgba(255,255,255,.7);margin-bottom:5px;letter-spacing:.012em}
.sunrise-val{font-size:20px;font-weight:500;font-variant-numeric:tabular-nums;
  color:rgba(255,255,255,.95);letter-spacing:.011em}
.arc-lit{filter:drop-shadow(0 0 6px rgba(255,214,110,.6))}
#sundot{filter:drop-shadow(0 0 7px rgba(255,226,150,.95))}
.muted{color:rgba(255,255,255,.75);font-size:13px;text-align:center;line-height:1.45}

/* ---------- content pages ---------- */
.panel{padding:26px 24px;margin-top:12px}
@media(max-width:600px){.panel{padding:20px 16px}}
h1,h2,h3{margin:0;letter-spacing:-.022em;text-wrap:balance;font-weight:600;color:var(--ink)}
h1{font-size:clamp(22px,3.4vw,28px)}
h2{font-size:clamp(17px,2.6vw,21px)}
h3{font-size:15px}
.panel p{margin:10px 0 0;color:var(--ink-2);max-width:68ch;font-size:14px}
.panel p b,.panel li b{color:var(--ink);font-weight:600}
.rule{height:1px;border:0;margin:16px 0 0;
  background:linear-gradient(90deg,rgba(203,167,57,.7),rgba(203,167,57,.2) 42%,rgba(25,26,28,.06))}
.eyebrow{font-size:10.5px;font-weight:700;color:var(--gold-dp);margin:0 0 7px;
  letter-spacing:.15em;text-transform:uppercase}

.statrow{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:18px}
@media(max-width:640px){.statrow{grid-template-columns:repeat(2,1fr)}}
.statbox{padding:14px 12px;border-radius:var(--r-md);text-align:center;
  background:var(--card-2);border:1px solid var(--line);box-shadow:none}
.statbox .n{font-size:25px;font-weight:600;letter-spacing:-.03em;
  color:var(--gold-dp);font-variant-numeric:tabular-nums;line-height:1}
.statbox .l{font-size:10.5px;color:var(--ink-3);margin-top:6px;line-height:1.35}

.tags{list-style:none;padding:0;margin:14px 0 0;display:flex;flex-wrap:wrap;gap:6px}
.tags li{font-size:12px;padding:5px 11px;border-radius:var(--r-pill);
  background:var(--card-2);border:1px solid rgba(203,167,57,.3);color:var(--ink-2)}

.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px}
@media(max-width:760px){.grid2{grid-template-columns:1fr}}

.tablewrap{overflow-x:auto;margin-top:16px;border-radius:var(--r-md);border:1px solid var(--line)}
table{border-collapse:collapse;width:100%;min-width:600px;font-size:13px;background:var(--card)}
th{text-align:left;font-size:11px;color:var(--ink-3);font-weight:600;
  padding:10px 14px;border-bottom:1px solid var(--line-2);white-space:nowrap}
td{padding:10px 14px;border-bottom:1px solid var(--line);color:var(--ink-2);vertical-align:top}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover td{background:var(--card-2)}
td.k{color:var(--ink);font-weight:600}

.btnrow{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}
.btn{position:relative;display:inline-flex;align-items:center;justify-content:center;
  padding:11px 20px;border-radius:var(--r-pill);text-decoration:none;overflow:hidden;
  font-weight:500;font-size:13.5px;color:var(--ink);
  background:linear-gradient(152deg,
    rgba(255,255,255,.52) 0%,rgba(255,255,255,.20) 48%,rgba(255,255,255,.42) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(24px) saturate(200%) brightness(1.06);
  border:1px solid var(--glass-edge);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.48),
    inset 0 0 18px rgba(255,255,255,.26),
    0 1px 2px rgba(25,26,28,.06),
    0 14px 30px -18px rgba(25,26,28,.40);
  transition:background .2s ease,color .2s ease,border-color .2s ease,
             box-shadow .28s cubic-bezier(.32,.72,0,1),transform .18s ease}
.btn:hover,.btn:focus-visible{
  color:var(--ink);border-color:rgba(25,26,28,.14);
  background:linear-gradient(152deg,
    rgba(255,255,255,.66) 0%,rgba(255,255,255,.32) 48%,rgba(255,255,255,.56) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,1),
    inset 0 -1px 0 rgba(255,255,255,.55),
    inset 0 0 22px rgba(255,255,255,.34),
    0 1px 2px rgba(25,26,28,.05),
    0 16px 34px -18px rgba(25,26,28,.40)}

/* Gold is solid rather than translucent: a light material stacked on a
   light ground is the one combination §12 says never to build, because
   the text stops holding. This one reads as polished metal instead. */
.btn-gold{color:#241B05;border:1px solid rgba(138,110,30,.45);
  background:linear-gradient(150deg,#F0DCA0 0%,#CBA739 52%,#A98726 100%);
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:
    inset 0 1px 0 rgba(255,251,235,.85),
    inset 0 -1px 0 rgba(120,94,20,.22),
    0 1px 2px rgba(25,26,28,.07),
    0 12px 26px -18px rgba(138,110,30,.40)}
.btn-gold:hover,.btn-gold:focus-visible{color:#241B05;
  background:linear-gradient(150deg,#F7E7B6 0%,#D8B54B 52%,#B8942C 100%);
  border-color:rgba(138,110,30,.62);
  box-shadow:
    inset 0 1px 0 rgba(255,253,244,.95),
    inset 0 -1px 0 rgba(120,94,20,.24),
    0 1px 2px rgba(25,26,28,.07),
    0 18px 34px -20px rgba(138,110,30,.46)}

.sitefoot{margin-top:32px;padding-top:16px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:8px 20px;justify-content:space-between;
  font-size:11.5px;color:var(--ink-3)}
.sitefoot a{color:var(--ink-3);text-decoration:none}
.sitefoot a:hover{color:var(--gold-dp)}

/* ============================================================
   Stark project pages — paper, grid, nothing else
   ============================================================ */
body.stark{background:var(--paper)}
.stark-wrap{position:relative;max-width:1320px;margin:0 auto;padding:0 24px 64px}
@media(max-width:600px){.stark-wrap{padding:0 14px 48px}}

.stark-top{padding:30px 0 22px;text-align:center}
.stark-top img{width:158px;height:auto;display:inline-block}
@media(max-width:600px){.stark-top img{width:132px}}

.pgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:34px 20px}
@media(max-width:1080px){.pgrid{grid-template-columns:repeat(4,1fr)}}
@media(max-width:760px){.pgrid{grid-template-columns:repeat(3,1fr);gap:26px 14px}}
@media(max-width:480px){.pgrid{grid-template-columns:repeat(2,1fr)}}

.pcell{text-decoration:none;color:inherit;display:block}
/* 21 of these on one page — rim, shadow and sheen only, no filter */
.pshot{
  aspect-ratio:1;border:1px solid var(--glass-edge);border-radius:16px;
  background:linear-gradient(152deg,
    rgba(255,255,255,.52) 0%,rgba(255,255,255,.14) 48%,rgba(255,255,255,.40) 100%);
  display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -1px 0 rgba(255,255,255,.45),
    inset 0 0 22px rgba(255,255,255,.22),
    0 1px 2px rgba(25,26,28,.06),
    0 16px 32px -20px rgba(25,26,28,.38);
  transition:border-color .3s ease,box-shadow .32s cubic-bezier(.32,.72,0,1),
             transform .32s cubic-bezier(.32,.72,0,1);
}
/* The covers are real photographs at mixed ratios — 4:3, 2.17:1, portrait —
   so they FILL the tile. Matting them instead (object-fit:contain) left each
   photo a different size inside its pane and the grid read as ragged. Filling
   crops a little off the long edge but gives one uniform set, which is what a
   project index is for. If these are ever replaced by the 2:1 poster plates,
   switch this back to contain so the whole composition survives. */
.pshot img{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  object-fit:cover;object-position:center;
}
.pshot .ph{
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-4);text-align:center;padding:8px;line-height:1.5;
}
.pcell:hover .pshot{
  border-color:rgba(203,167,57,.55);transform:translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    0 0 0 1px rgba(203,167,57,.18),
    0 2px 4px rgba(25,26,28,.05),
    0 26px 48px -24px rgba(25,26,28,.46)}
.pcell:hover .plabel{color:var(--gold-dp)}
.plabel{
  margin-top:11px;text-align:center;font-size:11px;font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink);
  line-height:1.4;transition:color .2s ease;
  min-height:2.8em;display:flex;align-items:flex-start;justify-content:center;
}
.pmeta{margin-top:4px;text-align:center;font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3)}

/* ---------- detail ---------- */
.dhead{max-width:860px;margin:0 auto;text-align:center;padding:6px 0 34px}
.dhead h1{font-size:clamp(22px,4vw,34px);font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.dkicker{font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--gold-dp);margin:0 0 12px;font-weight:700}
.dsum{margin:16px auto 0;max-width:64ch;font-size:14px;color:var(--ink-2);line-height:1.6}
.dscope{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin:18px auto 0;max-width:760px}
.dscope li{
  list-style:none;font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  padding:6px 13px;border-radius:var(--r-pill);
  border:1px solid var(--glass-edge);
  background:linear-gradient(152deg,rgba(255,255,255,.52),rgba(255,255,255,.18) 48%,rgba(255,255,255,.42));
  -webkit-backdrop-filter:blur(18px) saturate(190%);backdrop-filter:blur(18px) saturate(190%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.98),inset 0 -1px 0 rgba(255,255,255,.45),
    0 8px 18px -12px rgba(25,26,28,.34);
  color:var(--ink-2);
}

.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:6px}
@media(max-width:900px){.gallery{grid-template-columns:repeat(3,1fr);gap:10px}}
@media(max-width:560px){.gallery{grid-template-columns:repeat(2,1fr)}}
.gshot{aspect-ratio:4/3;border:1px solid var(--glass-edge);border-radius:14px;overflow:hidden;
  background:linear-gradient(152deg,rgba(255,255,255,.50),rgba(255,255,255,.16) 48%,rgba(255,255,255,.38));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(255,255,255,.42),
    inset 0 0 20px rgba(255,255,255,.22),0 14px 30px -20px rgba(25,26,28,.38)}
.gshot img{width:100%;height:100%;object-fit:cover;display:block}

.gempty{
  border:1px solid var(--glass-edge);border-radius:20px;
  padding:44px 24px;text-align:center;
  font-size:12px;letter-spacing:.06em;color:var(--ink-3);line-height:1.7;
  background:linear-gradient(152deg,
    rgba(255,255,255,.46) 0%,rgba(255,255,255,.16) 48%,rgba(255,255,255,.38) 100%);
  -webkit-backdrop-filter:blur(34px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(34px) saturate(200%) brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.48),
    inset 1px 0 0 rgba(255,255,255,.42),
    inset -1px 0 0 rgba(255,255,255,.42),
    inset 0 0 28px rgba(255,255,255,.26),
    0 26px 58px -30px rgba(25,26,28,.42);
}
.gempty b{display:block;color:var(--ink-2);font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;font-size:10.5px;margin-bottom:8px}
.gempty code{color:var(--teal-dp);font-size:11.5px}

.dsection{margin-top:46px}
.dsection h2{font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-3);text-align:center;margin-bottom:18px}
/* border-radius cannot clip a collapsed table, so it is separated */
.loctable{
  width:100%;border-collapse:separate;border-spacing:0;overflow:hidden;
  font-size:13px;min-width:0;border-radius:18px;
  border:1px solid var(--glass-edge);
  background:linear-gradient(152deg,
    rgba(255,255,255,.46) 0%,rgba(255,255,255,.16) 48%,rgba(255,255,255,.38) 100%);
  -webkit-backdrop-filter:blur(34px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(34px) saturate(200%) brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.48),
    inset 1px 0 0 rgba(255,255,255,.42),
    inset -1px 0 0 rgba(255,255,255,.42),
    inset 0 0 28px rgba(255,255,255,.26),
    0 30px 64px -32px rgba(25,26,28,.44);
}
.loctable td{padding:13px 18px}
.loctable tr:hover td{background:rgba(255,255,255,.34)}
.loctable td{padding:11px 12px;border-bottom:1px solid var(--line);
  color:var(--ink-2);vertical-align:top}
.loctable tr:last-child td{border-bottom:0}
.loctable td:first-child{color:var(--ink);font-weight:600;white-space:nowrap}
.loctable td:last-child{text-align:right;font-size:12px;color:var(--ink-3)}
@media(max-width:560px){
  .loctable,.loctable tbody,.loctable tr,.loctable td{display:block;width:100%}
  .loctable tr{border-bottom:1px solid var(--line);padding:10px 0}
  .loctable td{border:0;padding:2px 0;text-align:left!important}
}

/* The main nav, repeated at the foot of the stark pages.
   The nav element IS the capsule now, so its padding is the capsule's
   own geometry — adding padding-top here inflated the island and threw
   it off-centre. The gap and the hairline are handled outside it. */
/* The island sits under the logo on these pages now, exactly as it does
   on the others. It overrides .mainnav{margin:0 auto}, so it has to stay
   later in the file than that rule. */
.stark-nav{margin-bottom:42px}
@media(max-width:600px){.stark-nav{margin-bottom:30px}}

/* ============================================================
   Page flow — one quiet control at the foot of a page, bottom
   right, carrying the reader to the next one. Same glass body as
   .btn at a smaller gauge; the arrow is the only coloured mark.
   ============================================================ */
.pageflow{display:flex;justify-content:flex-end;margin-top:46px}
@media(max-width:600px){.pageflow{margin-top:34px}}

.flowbtn{
  position:relative;display:inline-flex;align-items:center;gap:11px;
  padding:9px 15px;border-radius:var(--r-pill);
  text-decoration:none;color:var(--ink);overflow:hidden;isolation:isolate;
  background:linear-gradient(152deg,
    rgba(255,255,255,.52) 0%,rgba(255,255,255,.20) 48%,rgba(255,255,255,.42) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(24px) saturate(200%) brightness(1.06);
  border:1px solid var(--glass-edge);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.96),
    inset 0 -1px 0 rgba(255,255,255,.26),
    inset 1px 0 0 rgba(255,255,255,.34),
    0 1px 2px rgba(25,26,28,.05),
    0 14px 30px -16px rgba(25,26,28,.34);
  transition:transform .22s cubic-bezier(.32,.72,0,1),
             box-shadow .22s cubic-bezier(.32,.72,0,1);
}
.flowbtn-k{
  font-size:9px;letter-spacing:.18em;text-transform:uppercase;
  font-weight:700;color:var(--ink-3);
}
.flowbtn-n{font-size:13px;font-weight:500;letter-spacing:-.006em;white-space:nowrap}
.flowbtn-a{width:15px;height:15px;flex:none;color:var(--gold-dp);
  transition:transform .3s cubic-bezier(.32,.72,0,1)}

.flowbtn:hover{
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.30),
    0 1px 2px rgba(25,26,28,.05),
    0 20px 38px -18px rgba(25,26,28,.40);
}
.flowbtn:hover .flowbtn-a{transform:translateX(4px)}
.flowbtn-back:hover .flowbtn-a{transform:translateX(-4px)}
.flowbtn:active{transform:scale(.985)}
.flowbtn:focus-visible{outline:2px solid var(--gold-dp);outline-offset:3px}
@media(prefers-reduced-motion:reduce){
  .flowbtn,.flowbtn-a{transition:none}
  .flowbtn:hover{transform:none}
  .flowbtn:hover .flowbtn-a,.flowbtn-back:hover .flowbtn-a{transform:none}
}
@media(prefers-reduced-transparency:reduce){
  .flowbtn{background:rgba(255,255,255,.92);
    -webkit-backdrop-filter:none;backdrop-filter:none}
}

/* ============================================================
   Page-to-page frost. A single fixed pane of liquid glass: it
   fades in over the page you are leaving and lifts off the page
   you arrive on, so the two reads as one frosted dissolve.
   It is an overlay, not a filter on the page itself — a filter
   would leave a permanent containing block behind and break the
   nav's own glass. It never touches scroll position.
   ============================================================ */
.pagefrost{
  position:fixed;inset:0;z-index:999;pointer-events:none;
  will-change:opacity;
  background:linear-gradient(152deg,
    rgba(255,255,255,.44) 0%,rgba(255,255,255,.16) 52%,rgba(255,255,255,.38) 100%);
  -webkit-backdrop-filter:blur(26px) saturate(170%) brightness(1.04);
          backdrop-filter:blur(26px) saturate(170%) brightness(1.04);
  animation:frostLift .52s cubic-bezier(.32,.72,0,1) both;
}
@keyframes frostLift{
  from{opacity:1;visibility:visible}
  99%{opacity:0;visibility:visible}
  to{opacity:0;visibility:hidden}
}
.pagefrost.is-leaving{animation:frostFall .3s cubic-bezier(.4,0,.6,1) both}
@keyframes frostFall{
  from{opacity:0;visibility:visible}
  to{opacity:1;visibility:visible}
}
@media(prefers-reduced-motion:reduce){.pagefrost{display:none}}
@media(prefers-reduced-transparency:reduce){
  .pagefrost{-webkit-backdrop-filter:none;backdrop-filter:none;
    background:rgba(255,255,255,.6)}
}

.stark-mail{text-align:center;margin:16px 0 0;font-size:11.5px;letter-spacing:.04em}
.stark-mail a{color:var(--ink-3);text-decoration:none}
.stark-mail a:hover{color:var(--gold-dp)}

:focus-visible{outline:2px solid var(--teal-dp);outline-offset:2px}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ============================================================
   Page arrival
   The cross-document view transition is GONE. It was the cause of the
   About page appearing at the bottom: the browser photographs the page
   you are leaving at the scroll position you were at, and during the
   transition it also re-applies its own scroll handling AFTER the hook
   where a script can intervene. No amount of scrolling-to-top from
   script reliably wins that race.

   The arrival fade below is pure CSS on the content, runs after the
   page has already loaded at the top, and cannot touch scroll at all.
   ============================================================ */
@media(prefers-reduced-motion:no-preference){
  .page,.stark-wrap,.ed{animation:dcArrive .5s cubic-bezier(.32,.72,0,1) both}
  @keyframes dcArrive{from{opacity:0}to{opacity:1}}
}

/* ============================================================
   Editorial pages — no cards, no bullets, no dividers.
   Measures are in em so they scale with the type: paragraphs at
   30em (~60 characters), headlines at 7em (~2-3 words a line),
   which is what makes headlines break the way Apple's do.
   Section padding is ~7x the body size; the gap from a headline
   to its own paragraph is ~1.3x. That 5.5:1 macro-to-micro ratio
   is what reads as quiet.
   ============================================================ */
.ed{max-width:910px;margin:0 auto;padding:0 24px 40px}
@media(max-width:734px){.ed{padding:0 20px 30px}}

.ed-sec{padding-top:122px}
.ed-sec:first-of-type{padding-top:68px}
@media(max-width:1068px){.ed-sec{padding-top:100px}}
@media(max-width:734px){.ed-sec{padding-top:64px}.ed-sec:first-of-type{padding-top:40px}}

.ed-center{text-align:center}
.ed-center .ed-h,.ed-center .ed-p{margin-left:auto;margin-right:auto}

.ed-eyebrow{
  font-size:24px;font-weight:600;letter-spacing:.009em;line-height:1.16667;
  color:var(--gold-dp);margin:0 0 .42em;
}
@media(max-width:1068px){.ed-eyebrow{font-size:21px;letter-spacing:.011em}}
@media(max-width:734px){.ed-eyebrow{font-size:19px;letter-spacing:.012em}}

.ed-h{
  font-size:48px;font-weight:400;letter-spacing:-.003em;line-height:1.08;
  max-width:7em;margin:0 0 22px;color:var(--ink);text-wrap:balance;
}
.ed-h-lg{font-size:64px;letter-spacing:-.009em;max-width:8em}
/* A headline made of place names: the parts are joined with non-breaking
   spaces so "Lower Mainland" and "Fraser Valley" can never split across
   lines, and the measure is widened because 7em forced exactly that. */
.ed-h-place{max-width:11em}
@media(max-width:1068px){
  .ed-h{font-size:40px;letter-spacing:0;margin-bottom:16px}
  .ed-h-lg{font-size:48px;letter-spacing:-.003em}
}
@media(max-width:734px){
  .ed-h{font-size:32px;letter-spacing:.004em;margin-bottom:13px}
  .ed-h-lg{font-size:36px;letter-spacing:.002em}
}

.ed-p{
  font-size:17px;line-height:1.47059;letter-spacing:-.022em;
  color:#515154;max-width:30em;margin:0;
}
.ed-p + .ed-p{margin-top:1.25em}
.ed-p-narrow{max-width:24em}

.ed-note{
  font-size:14px;line-height:1.42859;letter-spacing:-.016em;
  color:var(--ink-3);max-width:34em;margin:1.5em 0 0;
}
.ed-center .ed-note{margin-left:auto;margin-right:auto}

/* two article units side by side — a "list" made of small headlines */
.ed-row{display:grid;grid-template-columns:1fr 1fr;gap:64px;margin-top:0}
@media(max-width:1068px){.ed-row{gap:44px}}
@media(max-width:734px){.ed-row{grid-template-columns:1fr;gap:56px}}
.ed-row .ed-h{font-size:32px;letter-spacing:.004em;line-height:1.12;max-width:9em;margin-bottom:16px}
@media(max-width:734px){.ed-row .ed-h{font-size:28px;letter-spacing:.007em}}

/* statistics: big regular numeral, caption lifted out of flow so a row of
   them aligns on the numeral baseline whatever the caption length */
/* The captions used to be absolutely positioned, with a fixed margin
   below each badge standing in for their height — so a caption that ran
   long overlapped whatever sat beneath it. They are in normal flow now:
   the grid rows size themselves to the tallest caption and the collision
   cannot happen at any width or text size. */
/* About stays editorial — no cards around the prose, as before. The
   only glass here is a single plinth holding the statistics together
   as one object, which is what they are. */
.badges{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(9em,1fr));
  gap:40px 2.6em;
  margin-top:64px;padding:42px 44px;border-radius:30px;
  border:1px solid var(--glass-edge);
  background:linear-gradient(152deg,
    rgba(255,255,255,.56) 0%,rgba(255,255,255,.22) 48%,rgba(255,255,255,.46) 100%);
  -webkit-backdrop-filter:blur(46px) saturate(200%) brightness(1.06);
          backdrop-filter:blur(46px) saturate(200%) brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 -1px 0 rgba(255,255,255,.48),
    inset 1px 0 0 rgba(255,255,255,.42),
    inset -1px 0 0 rgba(255,255,255,.42),
    inset 0 0 28px rgba(255,255,255,.26),
    0 1px 2px rgba(25,26,28,.07),
    0 40px 80px -38px rgba(25,26,28,.46);
}
@media(max-width:734px){.badges{padding:28px 24px;border-radius:22px}}
@media(max-width:734px){
  .badges{grid-template-columns:repeat(2,1fr);gap:32px 1.6em;margin-top:44px}
}
.badge{text-align:left}
.badge-value{
  display:block;position:relative;left:-2px;white-space:nowrap;
  font-size:64px;font-weight:400;letter-spacing:-.009em;line-height:1;
  color:var(--teal-num);font-variant-numeric:tabular-nums;
}
/* a figure sitting inside running text */
.num{color:var(--teal-num)}
@media(max-width:1068px){.badge-value{font-size:48px;letter-spacing:-.003em}}
@media(max-width:734px){.badge-value{font-size:40px;letter-spacing:0}}
.badge-unit{font-size:.5em;font-weight:600;letter-spacing:.004em;margin-left:.06em}
.badge-caption{
  display:block;margin-top:.55em;
  font-size:14px;line-height:1.28577;letter-spacing:-.016em;color:var(--ink-3);
  text-wrap:pretty;
}

/* a row of names, set as type rather than pills */
.ed-names{
  display:flex;flex-wrap:wrap;gap:.45em 1.5em;margin:26px 0 0;padding:0;list-style:none;
  font-size:21px;letter-spacing:.011em;color:var(--ink);
}
@media(max-width:734px){.ed-names{font-size:19px;letter-spacing:.012em;gap:.4em 1.1em}}
.ed-center .ed-names{justify-content:center}

/* the single keyline Apple allows, given as much room as a section break */
.ed-keyline{border:0;border-bottom:1px solid #D2D2D7;margin:0;padding-bottom:48px}

.ed-cta{margin-top:39px;display:flex;flex-wrap:wrap;gap:10px}
.ed-center .ed-cta{justify-content:center}


/* ============================================================
   Response — feedback lands on the press, not the release,
   and every transition is short enough to feel direct.
   ============================================================ */
.navbtn,.btn,.pcell{-webkit-tap-highlight-color:transparent}
.navbtn:active,.btn:active{transform:scale(.975)}
.navbtn,.btn{transition:background .18s ease,color .18s ease,border-color .18s ease,
  transform .12s cubic-bezier(.2,.9,.3,1)}
.pcell .pshot{transition:border-color .25s ease,box-shadow .25s ease,
  transform .18s cubic-bezier(.2,.9,.3,1)}
.pcell:active .pshot{transform:scale(.982)}
.widget{transition:transform .2s cubic-bezier(.2,.9,.3,1)}

/* large surfaces materialise — blur and scale together — rather than
   simply fading, so they read as a material arriving */
@media(prefers-reduced-motion:no-preference){
  .widget{animation:materialise .62s cubic-bezier(.22,.7,.25,1) both}
  .widget:nth-child(2){animation-delay:.05s}
  .widget:nth-child(3){animation-delay:.1s}
  @keyframes materialise{
    from{opacity:0;transform:scale(.975);filter:blur(7px)}
    to  {opacity:1;transform:scale(1);filter:blur(0)}
  }
}

/* the accessibility signals the material has to answer to */
/* Someone who has asked for less transparency gets solid surfaces and
   no ground bloom — the glass becomes plain panels, which is the point
   of the setting, not a degraded version of it. */
@media(prefers-reduced-transparency:reduce){
  body::before,body::after{display:none}
  .lg,.lg-thick,.lg-thin,.btn,.gempty,.loctable,.badges,.pshot,.gshot,.dscope li{
    -webkit-backdrop-filter:none;backdrop-filter:none;
    background:var(--card);
  }
  .mainnav{-webkit-backdrop-filter:none;backdrop-filter:none;background:var(--card)}
  .mainnav::after{display:none}
  .btn::after,.pshot::after,.gempty::after,.badges::after{display:none}
}

/* Higher contrast: define every edge, drop the translucency that
   softens it, and stop the sheen washing over text. */
@media(prefers-contrast:more){
  :root{--line:rgba(25,26,28,.28);--line-2:rgba(25,26,28,.45);--ink-2:rgba(25,26,28,.82);
        --glass-edge:rgba(25,26,28,.38)}
  body::before,body::after{display:none}
  .lg,.lg-thick,.lg-thin,.btn,.gempty,.loctable,.badges,.pshot,.gshot{
    -webkit-backdrop-filter:none;backdrop-filter:none;
    background:var(--card);border-color:var(--glass-edge);
  }
  .navbtn,.btn{border-width:1px;border-color:var(--line-2)}
  .btn::after,.pshot::after,.gempty::after,.badges::after{display:none}
}

/* A sheen that animates is fine; one that moves under a pointer while
   the system asks for stillness is not. */
@media(prefers-reduced-motion:reduce){
  .btn::after,.pshot::after,.gempty::after,.badges::after{transition:none}
  .pcell:hover .pshot{transform:none}
}

/* The dot lattice belongs on the gradient cards, where bright dots on a
   deep ground read as a lit display. On paper, dark dots at 30% coverage
   read as damaged type, so the statistics stay solid ink. */
.badge-unit{color:var(--teal-num);font-family:"Inter",system-ui,sans-serif;
  font-size:.42em;font-weight:500;letter-spacing:.004em;margin-left:.08em;vertical-align:.12em}
