/* =========================================================
   WIP "Stage": one window pinned to the screen, morphing
   between a rectangle per section (see windowFor() in
   src/main.js). The page scrolls over it. The content exists
   twice: an ink copy clipped to OUTSIDE the window and a
   light copy clipped to INSIDE it, so text changes colour
   exactly at the window's edge, even mid-letter.
   ========================================================= */
html,body{background:var(--paper);transition:background-color .6s var(--ease)}
/* The scene owns the scrolling here and eases it itself, a frame at a time. With
   the site's CSS smooth scrolling still on, every one of those steps became an
   animation the next step interrupted: the page crawled and the menu fought the
   magnet. Off on this page only; the case studies keep it. */
html{scroll-behavior:auto}
/* The light copy MUST stay clickable. The ink copy is clip-pathed away inside the
   window, and a clip-path cuts hit-testing too, so inside the window the light copy
   is the only thing under the pointer. (Turning its pointer events off, 30 Sep,
   made every link inside the window dead and the work rows flicker between two
   projects as the window chased the pointer. Never again.) */
/* paper and ink follow the sunset, a little behind the sky */
.layer,.layer .dim,.layer .muted,.layer .rule,.layer .section__head,.layer .index__row,.layer .tl__row,.layer .tl,.layer .hero__foot{
  transition:color .6s var(--ease),border-color .6s var(--ease)}
:root[data-theme="dark"] .layer--light{text-shadow:0 1px 26px rgba(0,4,14,.55)}
.tools{z-index:81}
/* the header blur leaves with the nav */
.veil{transition:transform .5s var(--ease)}
.veil.is-hidden{transform:translateY(-100%)}
/* the menu stays above the window: a slimmer bar, and a veil that ends before the
   window's top edge (68px, windowFor in meadow.js) so that edge is never blurred */
.veil{height:62px}
/* short veil, so it has to be solid for most of its height: whatever scrolls up
   behind the menu disappears into paper before the soft edge */
.veil__tint{background:linear-gradient(to bottom,rgb(var(--paper-rgb)/1) 0%,rgb(var(--paper-rgb)/.97) 55%,rgb(var(--paper-rgb)/.6) 80%,rgb(var(--paper-rgb)/0) 100%)}
.nav{padding-block:.85rem}
/* a jump from the menu or the rail: the words leave, the window travels on its own,
   the words return with it (meadow.js toggles the class) */
.layer{transition:opacity .2s var(--ease)}
html.is-jumping .layer{opacity:0;transition-duration:.16s}
html.is-landing .layer{transition-duration:.5s}
#meadow{position:fixed;inset:0;width:100%;height:100%;display:block;z-index:0;pointer-events:none;clip-path:inset(100%)}
.layer{position:fixed;inset:0;overflow:hidden;z-index:1}
.layer--light{z-index:2;
  --ink:#F6F4EF;--ink-70:rgba(246,244,239,.88);--ink-45:rgba(246,244,239,.74);
  --rule:rgba(255,255,255,.34);--rule-strong:rgba(255,255,255,.5);--rule-soft:rgba(255,255,255,.18);
  --accent:#FFC4AE;--bar-a:#FFFFFF;--bar-b:rgba(255,255,255,.55);/* the current role over a blue sky: a real orange, not a tint of the paper one */--bar-acc-a:#FF7A3C;--bar-acc-b:#FFB98E;
  color:var(--ink);text-shadow:0 1px 22px rgba(10,22,34,.28)}
.clipper{position:absolute;inset:0;overflow:hidden}
.scroller{position:absolute;inset:0 0 auto 0;will-change:transform}
.spacer{pointer-events:none}


/* hero: the whole headline opens inside the window */
.s-hero{min-height:100vh;padding-top:18vh;display:flex;flex-direction:column}
/* text that sits inside the window keeps a margin from its edge */
.s-hero > .hero__meta,.s-hero > .display{margin-inline:clamp(1.25rem,3vw,3rem)}
.s-hero .display{font-size:clamp(3rem,10.4vw,10rem)}
.s-hero .hero__meta{padding-bottom:1.1rem}
/* the intro row is on screen from the first frame, centred in the air under the
   headline; the scroll that follows is the window travelling down to it */
/* the intro row is on screen from the first frame: the hero is one screen tall
   and the row's bottom sits 10vh up from its end, so it lands at 90vh whatever
   the copy runs to. The scroll after it is the window travelling down to it,
   which is where the row gets its moment. */
.s-hero .hero__foot{margin-top:auto;margin-bottom:10vh}

/* work: the list keeps to the left; the window holds the right */
.s-work{padding-top:16vh;padding-bottom:40vh}
.s-work .col{max-width:none}
/* the card the window is on loses the hairlines above and below it: a line drawn
   across a rounded window reads as a scratch (meadow.js sets is-sel / is-pre) */
.s-work .index__row,.s-work .section__head{transition:border-color .3s var(--ease)}
.s-work .index__row.is-sel,.s-work .index__row.is-pre,.s-work .section__head.is-pre{border-bottom-color:transparent}
/* the selected card is the window: its copy inside is a touch shaded for the white text */
.layer--light .s-work .index__row{background:rgba(6,14,6,.16)}
/* work: a steady rhythm. number | title with its status under it | disciplines, every row the same height */
.s-work .index__row{grid-template-columns:3.5rem minmax(0,1fr) minmax(0,18rem);padding-inline:clamp(1rem,2vw,1.75rem);gap:0 clamp(1rem,2vw,2rem);align-items:start;padding-block:clamp(1.5rem,2.6vw,2.25rem)}
.s-work .index__num,.s-work .index__disc{padding-top:.55rem}
.s-work .index__title{font-size:clamp(1.6rem,2.55vw,3rem);min-height:calc(1.02em + 2.6rem)}
.s-work .tag-soon{display:block;width:fit-content;margin:.75rem 0 0;vertical-align:0}
.s-work .index__disc{gap:.3rem .9rem;line-height:1.3}
/* hero: the words sit inside the window, not on its edge */
.s-hero .hero__foot{margin-inline:clamp(1.25rem,3vw,3rem)}
/* no rule over the intro row: when the window closes around it, that line ran
   straight across the scene */
.s-hero .hero__foot{border-top:0}
/* the descriptor is a label like Disciplines and Contact; the lede under it is display-sized, so it gets a little air */
.s-hero .hero__foot .lede{margin-top:.45rem}
.s-hero{margin-bottom:24vh;min-height:100vh} /* one screen; what follows is the window's travel to Work */
/* the intro row over the scene: it sits in the sky, so a crisp shadow on the letters is all it needs */
.layer--light .s-hero .hero__foot{text-shadow:0 1px 2px rgba(0,0,0,.34),0 0 14px rgba(20,40,70,.22)}
.layer--light .s-hero .hero__foot .dim{color:rgba(246,244,239,.92)}

.s-work .index__row{cursor:default}

/* pinned stages: the section scrolls, the stage holds still, the story plays */
.pin{position:relative;height:var(--sh,100vh);will-change:transform;--inner:calc(var(--pad) + clamp(1.25rem,3vw,3rem))}
.pin > .pin__label,.s-exp .pin > *{margin-inline:calc(var(--inner) - var(--pad))}
/* a soft shade under the words, only inside the window */
.scrim{position:absolute;inset:0;pointer-events:none;opacity:0;background:radial-gradient(ellipse 62% 42% at 22% 88%,rgba(6,12,4,.5) 0%,rgba(6,12,4,.22) 55%,transparent 100%),linear-gradient(to top,rgba(8,16,6,.6) 0%,rgba(8,16,6,.32) 35%,rgba(8,16,6,.08) 65%,transparent 85%)}
/* the small text over the scene gets a soft shadow of its own */
.layer--light .beats__body{text-shadow:0 1px 3px rgba(0,0,0,.5)}
.scrim--center{background:radial-gradient(ellipse 46% 34% at 50% 52%,rgba(8,16,6,.42) 0%,rgba(8,16,6,.18) 55%,transparent 100%)}
.layer:not(.layer--light) .scrim{display:none}
.pin__label{position:absolute;top:13vh}

/* step groups: their pieces fade in place, one after another (meadow.js sets the opacity) */
[data-step]{will-change:opacity,filter}
.beats__big > span[data-step]{display:inline-block}
/* about: a panoramic window; the words arrive one phrase at a time, coming into focus */
.s-about{height:520vh}
.beats{position:absolute;left:var(--inner);right:var(--inner);bottom:12vh}
.beats__big{max-width:15em;font-size:clamp(2rem,4.6vw,4.6rem);line-height:1.02}
.beats__big > span{display:inline-block;will-change:transform,opacity,filter}
.beats__body{max-width:40rem;margin-top:1.4rem;will-change:transform,opacity,filter}

/* experience: the timeline sits in the sky; the grass holds the bottom of the frame */
.s-exp{height:360vh}
/* Experience's heading moved to the band, so its words come out of the flow
   entirely and the list climbs into the sky by their height plus their padding.
   What the head still does is draw the rule over the axis and anchor the snap. */
.s-exp .section__head{position:relative;padding-top:10vh;padding-bottom:0;border-bottom:0}
/* with the heading gone the head's rule and the timeline's own top border were
   two hairlines a few pixels apart; the timeline keeps its, the head drops one */
.s-exp .section__head > *{position:absolute;opacity:0;pointer-events:none}
/* and none over the timeline: on a narrow screen it landed on the window's own
   top edge, two lines in the same place */
.s-exp .tl{margin-top:1vh;border-top:0}
.s-exp .tl__row{padding-top:.4rem;padding-bottom:.4rem}  /* tight enough that six roles clear the tree line and the grass is left to the year */
.s-exp .tl__note{display:none}
.s-exp .tl__bar{transform-origin:0 50%;scale:1 1;transition:none}
.s-exp .tl__axis,.s-exp .tl__row{grid-template-columns:minmax(0,15rem) minmax(0,1fr) minmax(0,8rem)}
.s-exp .tl__label .mono{padding-top:.15rem}
.s-exp .tl__scale{position:relative}
.playhead{position:absolute;top:-.3rem;bottom:-.3rem;width:1px;background:currentColor;opacity:.9}
/* the year sits in the window's bottom-right corner, sized to the room left under the list (set in meadow.js) */
.year{position:absolute;right:var(--inner);bottom:calc(var(--band) + clamp(1rem,2.4vw,2.25rem));font-size:var(--year-size,clamp(3rem,7vw,7rem));margin:0 !important;line-height:.9;letter-spacing:-.05em;font-weight:500;font-variant-numeric:tabular-nums;opacity:.9}

/* education & tools: back to paper, window on the right */
/* a pinned stage: the block holds opposite the window, in the middle of the left
   column, and plays its arrival and its exit there rather than scrolling past */
.s-tools{height:200vh}
.s-tools .pin{display:grid;align-content:center;padding-bottom:12vh}  /* the padding sits the block a little above the middle, where it reads better
     against the window than dead centre */
.s-tools .col{max-width:min(50vw, 820px)}
/* education & tools: one hairline, one label per block, no rules between items */
/* no rule over Education: there is nothing above it for a rule to divide */
.et{padding-top:clamp(1.5rem,3vw,2.5rem);display:grid;gap:clamp(2.75rem,6vh,4.5rem)}
.et__label{margin-bottom:1.1rem}
.et__edu{list-style:none;margin:0;padding:0;display:grid;gap:.55rem}
.et__edu li{display:grid;grid-template-columns:4.5rem 1fr;align-items:baseline;font-size:clamp(1.25rem,1.9vw,1.75rem);letter-spacing:-.025em;line-height:1.2}
.et__tools{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1.4rem 2rem;margin:0}
.et__tools dt{margin-bottom:.3rem}
.et__tools dd{margin:0;font-size:1.05rem;letter-spacing:-.015em;line-height:1.35}
@media(max-width:600px){.et__tools{grid-template-columns:1fr}}

/* contact: the address sits in the sky */
.s-contact{position:relative;height:150vh}
.s-contact .pin{position:relative;height:var(--sh,100vh)}
/* the last screen: the address centred in the window, the footer in the band beneath it */
.contact-stage{position:absolute;left:var(--wpad);right:var(--wpad);top:68px;bottom:var(--band);display:grid;place-items:center;text-align:center}
.contact-label{position:absolute;top:clamp(1.25rem,3vw,2.25rem);left:clamp(1.25rem,3vw,2.5rem)}
.contact-center .contact__mail{display:inline-block}
.contact-center .links{display:flex;justify-content:center;padding-top:1.4rem}
.m-foot{white-space:nowrap;position:absolute;left:var(--wpad);right:calc(var(--wpad) + 3.6rem);bottom:0;height:var(--band);display:flex;align-items:center;justify-content:space-between}
@media(max-width:600px){.m-foot span:last-child{display:none}}
/* the day/night button: right edge on the window's edge, centred in the band */
.tools{right:var(--wpad);bottom:max(.5rem,calc((var(--band) - 2.4rem) / 2))}

/* the section's name, in the band under the window: ink on paper, so it never
   sinks into grass or sky. It holds still and cross-fades; the window it labels
   does not move between these sections either. Right-hand meta clears the
   day/night button the same way the footer does. */
.stage{
  position:fixed;left:var(--wpad);right:calc(var(--wpad) + 3.6rem);bottom:0;height:var(--band);
  z-index:79;display:flex;align-items:center;justify-content:space-between;gap:1rem;
  white-space:nowrap;pointer-events:none;
  opacity:0;transition:opacity .34s var(--ease);
}
.stage.is-in{opacity:1}
/* the headings it stands in for stay in the flow: one is a scroll-snap anchor,
   the other draws the rule above the timeline. They are simply not drawn. */
.s-about .pin__label{opacity:0}

@media(max-width:820px){
  .s-hero{padding-top:calc(46vh - 6rem)}
  .s-work .col,.s-tools .col{max-width:none}
  /* the run-out after the last project, and the air before Education & Tools:
     both were sized for a wide screen and read as dead space on a phone */
  /* narrow: the window takes the top third of the screen, so the block sits in
     the paper below it rather than in the middle of the viewport, and tightens
     up enough to fit there without touching the window's edge */
  .s-tools{height:180vh}
  .s-tools .pin{align-content:end;padding-bottom:9vh}
  .s-tools .et{gap:clamp(1.5rem,3.5vh,2.4rem);padding-top:clamp(.9rem,2.5vw,1.4rem)}
  .s-tools .et__label{margin-bottom:.7rem}
  .s-tools .et__edu{gap:.4rem}
  .s-tools .et__edu li{font-size:clamp(1.1rem,4.4vw,1.4rem)}
  .s-tools .et__tools{gap:1rem 1.5rem}
  .s-work{padding-top:10vh;padding-bottom:26vh}
  /* hero intro row: disciplines and contact each get the full width, so the list doesn't break word by word */
  .s-hero .hero__foot > *:nth-child(2),.s-hero .hero__foot > *:nth-child(3){grid-column:span 2}
  /* education & tools: a little inset, so the words never touch the window's edge */
  .s-tools .col{padding-inline:1.1rem}
  .s-work .index__row{grid-template-columns:2.25rem minmax(0,1fr);gap:0 .75rem}
  .s-work .index__disc{grid-column:2;padding-top:.9rem}
  .s-work .index__title{min-height:0}
  .s-hero{padding-top:16vh}
  .s-exp .tl__note{display:none}
  /* a phone screen is tall against this much copy, so the air after the intro
     row is cut to about a third of what it is on a wide screen */
  .s-hero{margin-bottom:8vh}
  /* the section rail stands on the window's right edge; on a phone About's words
     run the full width, so they stop short of it */
  /* the section rail sits in the window's bottom-right corner on a phone, so what
     lives at the bottom of the window moves up to clear it */
  .beats{bottom:calc(var(--band) + 3.9rem)}
  .year{bottom:calc(var(--band) + 3.75rem)}
}
@media(max-width:1000px){
  /* experience on a phone or narrow window: one compact line per role (title · dates) with its bar under it, so all six fit the window */
  .s-exp .tl__axis{display:none}
  .s-exp .tl{margin-top:.5rem}
  .s-exp .tl__row{grid-template-columns:minmax(0,1fr);gap:0;padding-top:.5rem;padding-bottom:.5rem}
  .s-exp .tl__label{display:flex;justify-content:space-between;align-items:baseline;gap:.75rem}
  .s-exp .tl__label > p.mono:not(.tl__dates){display:none}
  .s-exp .tl__role{font-size:.95rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .s-exp .tl__dates{padding-top:0;white-space:nowrap;font-size:.625rem}
  .s-exp .tl__track{grid-column:1;height:.55rem;margin-top:.35rem}
  .s-exp .section__head{padding-top:8vh}
  /* With the role alone on its line, the static link underline and the row's
     own border read as two stray rules under every job. The bar's track is the
     only line a row needs: it is the one that means something. */
  .s-exp .tl__label a{border-bottom:0;padding-bottom:0}
  .s-exp .tl__row{border-bottom:0}
}
@media(max-width:820px){
  /* a phone: the timeline takes the sky, six roles spread over it instead of huddling at
     the top (after the 1000px rules above, which set the compact row this replaces) */
  .s-exp .tl__row{padding-top:clamp(.8rem,2.5vh,1.6rem);padding-bottom:clamp(.8rem,2.5vh,1.6rem)}
}

/* ---------- the section rail ----------
   Three icon buttons on the window's right edge while About, Experience and
   Education are on stage. They sit over the scene, so they are drawn like the
   light copy: white line icons on a little frosted disc; the section you are in
   is the filled one. The name slides out on hover or keyboard focus. */
.rail{position:fixed;top:0;left:0;z-index:78;display:flex;flex-direction:column;gap:.55rem;
  opacity:0;visibility:hidden;transition:opacity .35s var(--ease),visibility 0s linear .35s;
  will-change:transform}
.rail.is-in{opacity:1;visibility:visible;transition:opacity .35s var(--ease),visibility 0s}
.rail a{position:relative;display:grid;place-items:center;width:2.25rem;height:2.25rem;border-radius:50%;
  color:#F6F4EF;background:rgba(8,16,8,.22);border:1px solid rgba(255,255,255,.34);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease)}
.rail a:hover{background:rgba(8,16,8,.38);border-color:rgba(255,255,255,.6)}
.rail a[aria-current="true"]{background:#F6F4EF;color:#12110F;border-color:#F6F4EF}
.rail .ico{width:1.05rem;height:1.05rem}
/* Conrado's SF Symbols are solid shapes, drawn as supplied. The site's generic .ico
   rule strokes outlines (fill:none, stroke), which turned both versions into wiry
   tracings of themselves; these are painted, never stroked. */
.rail .ico--sf{fill:currentColor;stroke:none}
/* the outline version at rest; the filled one on hover, keyboard focus, and for the
   section you are in */
.rail .ico.is-fill{display:none}
.rail a:hover .ico.is-line,.rail a:focus-visible .ico.is-line,.rail a[aria-current="true"] .ico.is-line{display:none}
.rail a:hover .ico.is-fill,.rail a:focus-visible .ico.is-fill,.rail a[aria-current="true"] .ico.is-fill{display:block}
/* on a phone: a row in the window's bottom-right corner, within reach of a thumb */
.rail.rail--row{flex-direction:row}
.rail--row .rail__tip{right:auto;left:50%;top:auto;bottom:calc(100% + .5rem);transform:translate(-50%,6px)}
.rail--row a:hover .rail__tip,.rail--row a:focus-visible .rail__tip{transform:translate(-50%,0)}
.rail__tip{position:absolute;right:calc(100% + .5rem);top:50%;white-space:nowrap;pointer-events:none;
  font-family:var(--mono);font-size:.625rem;letter-spacing:.08em;text-transform:uppercase;line-height:1;
  padding:.5rem .7rem;border-radius:99px;color:#F6F4EF;background:rgba(8,16,8,.42);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  opacity:0;transform:translate(6px,-50%);transition:opacity .25s var(--ease),transform .35s var(--ease)}
.rail a:hover .rail__tip,.rail a:focus-visible .rail__tip{opacity:1;transform:translate(0,-50%)}

/* dev panel (H hides) */
.hud{position:fixed;left:50%;transform:translateX(-50%);bottom:1rem;z-index:80;display:flex;gap:1rem;align-items:center;white-space:nowrap;
  padding:.6rem .9rem;border-radius:999px;background:rgba(18,17,15,.72);color:#EFEDE7;font-family:var(--mono);font-size:.625rem;letter-spacing:.08em;text-transform:uppercase}
.hud.is-hidden{display:none}
.hud button{font:inherit;color:inherit;background:rgba(239,237,231,.12);border:0;border-radius:999px;padding:.35rem .7rem;cursor:pointer}
