/* ═══════════════════════════════════════════════════════════════════════
   NORDEVO · Konserni. "Rakenne, joka kantaa." (rebuilt 2026-09-04, Anton:
   the drawing-office figure is not what the site is looking for). The
   group is staged as the marks themselves: after the masthead and the
   registry numbers, the four companies come one screen at a time on a
   pinned stage — kicker and registry line, the mark performing its own
   arrival at specimen scale, the claim with its stamped period, the body,
   the fact rows in air, and where a photograph exists, a print hung on
   the right chasing the scroll on its own clock. A scroll step hands one
   company to the next on one clock (konserni.js). Phones, short
   viewports, no-JS, reduced motion and ?flat=1 get the same four pages
   stacked with air. No hairlines on this page but the nav's: the numbers
   row and the fact rows separate by air alone. Loaded after nordevo.css
   and alasivu.css on /konserni/ only. Print hooks: ?flat=1 the whole page
   still · ?vp=<id> one section at the top · ?k=<0..3> one company held
   on the stage.
   ═══════════════════════════════════════════════════════════════════════ */

/* ═══ AVAUS: masthead — claim left, one sentence hanging right and low ═══ */
.kavaus { padding:19vh 12vw 0; }
.kmast { display:grid; grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);
  gap:2vh 6vw; align-items:end; }
.kotsa { margin-top:2.5vh; font-family:var(--disp); font-weight:500;
  font-size:clamp(34px,4.5vw,68px); letter-spacing:-.028em; line-height:1.08; }
/* the h1 rises through hand-authored line masks (subpages have no splitLr) */
.js .kotsa.rv { opacity:1; transform:none; }
.kotsa .rj { display:block; overflow:hidden; padding-bottom:.12em; margin-bottom:-.12em; }
.kotsa .rji { display:block; }
.js .kotsa .rji { transform:translateY(114%); }
.js .kotsa.on .rji { transform:none; transition:transform 1s cubic-bezier(.22,1,.36,1); }
.js .kotsa.on .rj:nth-child(2) .rji { transition-delay:.09s; }
.kotsa .liitos { white-space:nowrap; }
.kotsa .p { display:inline-block; color:var(--sun); }
.js .kotsa .p { transform:scale(0); transform-box:border-box; transform-origin:60% 60%; }
.js .kotsa.on .p { animation:dotpop .5s cubic-bezier(.3,1.6,.4,1) 1.05s forwards; }
.kjohd { justify-self:end; font-size:clamp(14.5px,1.22vw,16.5px); line-height:1.75;
  color:var(--faded); max-width:46ch; padding-bottom:.6vh; }

/* ═══ LUVUT: the books (the careers live on the front page) ═══ */
.kluvut { padding:13vh 12vw 6vh; }
.kluvut .luvut { grid-template-columns:1.15fr .8fr 1.1fr .85fr; margin-top:5vh; }
.klfine { margin-top:6vh; font-size:14.5px; color:var(--muted); line-height:1.8;
  max-width:64ch; }

/* ═══ YHTIÖT · the still page: four composed pages stacked with air.
   Grid: header across; the mark left with the print (where one exists)
   hung beside it on the right; the claim and body under the mark, the
   fact rows under the print. The stage below only pins this and plays
   the arrivals one page at a time. ═══ */
.kyhtiot { position:relative; }
.klava { position:relative; }
.kkerros { padding:13vh 12vw 5vh; display:grid;
  grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);
  grid-template-areas:"paa paa" "logo aside" "sis aside";
  grid-template-rows:auto auto 1fr; column-gap:6vw; align-content:start; }
.kkerros:last-of-type { padding-bottom:15vh; }
.kpaa { grid-area:paa; display:flex; justify-content:space-between;
  align-items:baseline; gap:2vh 4vw; flex-wrap:wrap; }
.krek { font-family:var(--sans); font-weight:500; font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--muted);
  font-variant-numeric:tabular-nums; }
.klogo { grid-area:logo; color:var(--ink); margin-top:6vh; align-self:start; }
.ksis { grid-area:sis; margin-top:5.5vh; }
.laside { grid-area:aside; margin-top:6vh; }
.lvaite { font-family:var(--disp); font-weight:500;
  font-size:clamp(27px,2.9vw,44px); letter-spacing:-.025em; line-height:1.12; }
.lvaite .liitos { white-space:nowrap; }
.lvaite .p { display:inline-block; color:var(--sun); }
.lbody { margin-top:3vh; font-size:clamp(15px,1.3vw,17.5px); line-height:1.78;
  color:var(--faded); max-width:52ch; }
.lfine { margin-top:2.6vh; font-size:14px; color:var(--muted); max-width:52ch; }
.lulos { margin-top:3.4vh; }
.ulosl { font-family:var(--sans); font-size:13px; letter-spacing:.05em;
  color:var(--ink); text-decoration:none; white-space:nowrap; padding-bottom:2px;
  background:linear-gradient(90deg,var(--sun),var(--sun)) no-repeat 0 100%/100% 1px;
  transition:color .4s ease; }
.ulosl::after { content:" ↗"; }
.ulosl:hover { color:var(--sun); }
/* the fact rows: label dim, value clear, air does the framing */
.lfaktat { margin:0; }
.lfaktat .lf { padding:0 0 3.2vh; }
.lfaktat .ll { font-family:var(--sans); font-weight:500; font-size:10.5px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--muted); }
.lfaktat .la { margin:.9vh 0 0; font-family:var(--sans); font-weight:500;
  font-size:clamp(15px,1.3vw,18px); letter-spacing:-.015em; color:var(--ink); }
.lfaktat .ls { display:block; margin-top:.5vh; font-family:"Newsreader",Georgia,serif;
  font-weight:400; font-size:13.5px; letter-spacing:0; line-height:1.6; color:var(--muted); }
/* the print: hung on the right beside the mark; it develops on arrival */
.lprint { margin:0 0 4.5vh; }
.lprint img { width:100%; height:auto; }
.lprint figcaption { margin-top:1.4vh; display:flex; flex-wrap:wrap;
  align-items:baseline; gap:.5em 1.1em; }
.pnimi { font-family:var(--sans); font-weight:500; font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink); }
.pselite { font-size:13.5px; color:var(--muted); }
.plinkki { font-family:var(--sans); font-size:12px; letter-spacing:.05em;
  color:var(--faded); text-decoration:none; padding-bottom:2px;
  background:linear-gradient(90deg,var(--sun),var(--sun)) no-repeat 0 100%/100% 1px;
  transition:color .4s ease; }
.plinkki:hover { color:var(--ink); }

/* the logo specimens */
.llogoE .elogo, .llogoA .ealogo { --dot:var(--sun); display:block; width:100%; height:auto; overflow:visible; }
.eseam { opacity:.3; }
.lsub { display:block; width:calc(100% + .5em); margin-top:1.6vh;
  font-family:var(--sans); font-size:clamp(13px,1.25vw,17px); font-weight:500;
  text-transform:uppercase; text-align:right; letter-spacing:.5em; color:var(--ink); }
.llogoW .wlogo { display:block; width:100%; height:auto; }
.llogoH { display:flex; align-items:flex-end; gap:clamp(22px,2.6vw,40px); }
.hmer { display:block; height:clamp(120px,12vw,176px); width:auto; flex:none; }
.hnim { display:flex; flex-direction:column; gap:.6em; font-family:var(--disp);
  font-size:clamp(13px,1.25vw,17px); font-weight:400; letter-spacing:.32em;
  line-height:1; color:var(--ink); padding-bottom:6px; }
.hnim i { font-style:normal; }

/* ═══ ARRIVALS: one page's parts arrive on their own beats once the page
   is .on — line masks for the display lines, the mark's own performance,
   the rest fading up in order, the print developing. Enter states are
   gated behind .js:not(.static) so the first paint, no-JS and reduced
   motion never meet them. ═══ */
.k-mask { display:block; overflow:hidden; padding-bottom:.12em; margin-bottom:-.12em; }
.k-in { display:block; }
.js:not(.static) .kkerros:not(.on) .k-in { transform:translateY(112%); }
.js:not(.static) .kkerros.on .k-in { transform:none;
  transition:transform 1s cubic-bezier(.22,1,.36,1) .15s; }
.js:not(.static) .kkerros.on .krek .k-in { transition-delay:.22s; }
.js:not(.static) .kkerros.on .lvaite .k-in { transition-delay:.42s; }
.js:not(.static) .kkerros:not(.on) .lvaite .p { transform:scale(0); transform-box:border-box;
  transform-origin:60% 60%; }
.js:not(.static) .kkerros.on .lvaite .p { animation:dotpop .5s cubic-bezier(.3,1.6,.4,1) 1.15s forwards; }
.js:not(.static) .kkerros:not(.on) .k-fade { opacity:0; transform:translateY(14px); }
.js:not(.static) .kkerros.on .k-fade { opacity:1; transform:none;
  transition:opacity 1.1s cubic-bezier(.22,1,.36,1) .45s, transform 1.1s cubic-bezier(.22,1,.36,1) .45s; }
.js:not(.static) .kkerros.on .lfine { transition-delay:.55s; }
.js:not(.static) .kkerros.on .lulos { transition-delay:.62s; }
.js:not(.static) .kkerros.on .lf:nth-child(1) { transition-delay:.5s; }
.js:not(.static) .kkerros.on .lf:nth-child(2) { transition-delay:.58s; }
.js:not(.static) .kkerros.on .lf:nth-child(3) { transition-delay:.66s; }
.js:not(.static) .kkerros.on .lprint { transition-delay:.35s; }
/* the print develops from duotone as it arrives */
.js:not(.static) .lprint img { filter:sepia(.45) saturate(.6) contrast(.95) brightness(1.02);
  transition:filter 1.8s ease .5s; }
.js:not(.static) .kkerros.on .lprint img { filter:none; }
/* emoyhtiö: the wordmark settles, the seam of light passes the D–E channel */
.js:not(.static) .kkerros:not(.on) .llogoE .elogo { --dot:var(--paper); opacity:0; transform:translateY(16px); }
.js:not(.static) .kkerros.on .llogoE .elogo { --dot:var(--sun); opacity:1; transform:none;
  transition:opacity 1.1s cubic-bezier(.22,1,.36,1) .3s,
             transform 1.1s cubic-bezier(.22,1,.36,1) .3s,
             --dot .7s ease 1.3s; }
.js:not(.static) .kkerros.on .llogoE .eseam { animation:seamPass 2s ease 1.4s 1; }
/* Asunnot: the wordmark settles, ASUNNOT tracks in under it */
.js:not(.static) .kkerros:not(.on) .llogoA .ealogo { --dot:var(--paper); opacity:0; transform:translateY(16px); }
.js:not(.static) .kkerros.on .llogoA .ealogo { --dot:var(--sun); opacity:1; transform:none;
  transition:opacity 1.1s cubic-bezier(.22,1,.36,1) .3s,
             transform 1.1s cubic-bezier(.22,1,.36,1) .3s,
             --dot .7s ease 1.6s; }
.js:not(.static) .kkerros:not(.on) .lsub { opacity:0; letter-spacing:.85em; }
.js:not(.static) .kkerros.on .lsub { opacity:1; letter-spacing:.5em;
  transition:opacity .9s ease 1s, letter-spacing 1.4s cubic-bezier(.22,1,.36,1) 1s; }
/* Nordewood: the timber bars rise from the baseline */
.js:not(.static) .llogoW .palkki { transform-box:fill-box; transform-origin:50% 100%; }
.js:not(.static) .kkerros:not(.on) .llogoW .palkki { transform:scaleY(0); }
.js:not(.static) .kkerros.on .llogoW .palkki { transform:none;
  transition:transform .9s cubic-bezier(.22,1,.36,1) .35s; }
.js:not(.static) .kkerros.on .llogoW .palkki.puu { transition-delay:.55s; }
.js:not(.static) .kkerros.on .llogoW .palkki:nth-child(3) { transition-delay:.75s; }
.js:not(.static) .kkerros:not(.on) .llogoW .nsana { opacity:0; }
.js:not(.static) .kkerros.on .llogoW .nsana { opacity:1; transition:opacity 1.2s ease 1.1s; }
/* HNL: the monoline mark draws itself stroke by stroke, smile last */
.js:not(.static) .llogoH .hv { stroke-dasharray:1; }
.js:not(.static) .kkerros:not(.on) .llogoH .hv { stroke-dashoffset:1; }
.js:not(.static) .kkerros.on .llogoH .hv { stroke-dashoffset:0; }
.js:not(.static) .kkerros.on .h1 { transition:stroke-dashoffset 1.05s cubic-bezier(.45,.1,.3,.9) .3s; }
.js:not(.static) .kkerros.on .h2 { transition:stroke-dashoffset .24s ease-out 1.25s; }
.js:not(.static) .kkerros.on .h3 { transition:stroke-dashoffset .38s ease-out 1.45s; }
.js:not(.static) .kkerros.on .h4 { transition:stroke-dashoffset .38s ease-out 1.77s; }
.js:not(.static) .kkerros.on .h5 { transition:stroke-dashoffset .28s ease-out 2.09s; }
.js:not(.static) .kkerros.on .h6 { transition:stroke-dashoffset .7s cubic-bezier(.3,.6,.3,1) 2.35s; }
.js:not(.static) .kkerros:not(.on) .hnim i { opacity:0; transform:translateY(10px); }
.js:not(.static) .kkerros.on .hnim i { opacity:1; transform:none;
  transition:opacity .8s ease, transform .8s cubic-bezier(.22,1,.36,1); }
.js:not(.static) .kkerros.on .hnim i:nth-child(1) { transition-delay:1.3s; }
.js:not(.static) .kkerros.on .hnim i:nth-child(2) { transition-delay:1.48s; }
.js:not(.static) .kkerros.on .hnim i:nth-child(3) { transition-delay:1.66s; }
/* a page snapped into place (jumps over more than one step) plays nothing */
.kkerros.snap, .kkerros.snap * { transition:none !important; animation:none !important; }

/* the meter, the hint and the parking anchors exist only on the stage */
.kmittari, .kvihje, .kankkurit { display:none; }

/* ═══ THE STAGE: desktop, tall enough, JS, motion. The section grows to
   one beat per company plus a tail; the stage pins; every page sits on
   it at once and konserni.js turns exactly one .on. Each page's body
   rises in and lifts away with the scroll itself (konserni.js writes
   opacity and translate per frame); the parts inside play their timed
   arrival from the moment the page turns .on. ═══ */
@media (min-width:861px) and (min-height:700px) {
  /* the page parks on a company through native scroll snap: one anchor per page at its
     rest (0.6 viewports of scroll apart, the same BEAT as konserni.js), proximity so nothing
     else on the page snaps, stop:always so a fling never passes a page. The nav's
     scroll-padding would shift every rest by its height, so it is zero here; the stage pins
     at top:0 and the meter, the front page's rows and the keys all land through the script. */
  html { scroll-snap-type:y proximity; scroll-padding-top:0; }
  body.js:not(.static) .kyhtiot { height:calc(100vh + 3 * 60vh); }   /* the last rest is the moment the stage lets go */
  body.js:not(.static) .kankkurit { display:block; position:absolute; inset:0; pointer-events:none; }
  body.js:not(.static) .kankkurit i { position:absolute; left:0; width:1px; height:100vh;
    scroll-snap-align:start; scroll-snap-stop:always; }
  body.js:not(.static) .kankkurit i:nth-child(2) { top:60vh; }
  body.js:not(.static) .kankkurit i:nth-child(3) { top:120vh; }
  body.js:not(.static) .kankkurit i:nth-child(4) { top:180vh; }
  body.js:not(.static) .klava { position:sticky; top:0; height:100vh; overflow:hidden;
    background:var(--paper); }
  /* the page's body (opacity, translate, visibility) is written per frame
     by konserni.js and follows the scroll; only the parts inside transition */
  body.js:not(.static) .kkerros { position:absolute; inset:0; padding:12vh 12vw 0;
    opacity:0; visibility:hidden; pointer-events:none; will-change:transform,opacity; }
  body.js:not(.static) .kkerros.on { pointer-events:auto; }
  body.js:not(.static) .kkerros:last-of-type { padding-bottom:0; }
  /* the print hangs to the right of the mark and chases the scroll on its
     own clock (konserni.js writes translate) */
  body.js:not(.static) .lprint { will-change:translate; }
  /* the print's height follows the column's width and the stage's does not: on a wide, short
     window (1536x730, 1920x820) the last fact row fell under the stage's bottom edge. On the
     stage the print keeps to a share of the height and crops inside its own frame. */
  body.js:not(.static) .lprint img { max-height:36vh; object-fit:cover; }
  body.js:not(.static) .kmittari { display:flex; flex-direction:column; gap:1.8vh;
    position:absolute; right:5vw; top:50%; transform:translateY(-50%); margin:0;
    padding:0; list-style:none; z-index:5; }
  body.js:not(.static) .kmittari button { border:0; background:none; cursor:pointer;
    padding:4px 0; font-family:var(--sans); font-weight:500; font-size:10.5px;
    letter-spacing:.18em; color:var(--muted); font-variant-numeric:tabular-nums;
    background:linear-gradient(90deg,var(--sun),var(--sun)) no-repeat 0 100%/0 1px;
    transition:color .4s ease, background-size .5s cubic-bezier(.22,1,.36,1); }
  body.js:not(.static) .kmittari button.on { color:var(--ink); background-size:100% 1px; }
  body.js:not(.static) .kmittari button:hover { color:var(--ink); }
  body.js:not(.static) .kvihje { display:block; position:absolute; left:12vw; bottom:6vh;
    margin:0; font-family:var(--sans); font-size:10.5px; letter-spacing:.18em;
    text-transform:uppercase; color:var(--muted); opacity:0; transition:opacity .8s ease; }
  body.js:not(.static) .klava.eka .kvihje { opacity:.85; transition-delay:1.8s; }
}

/* ═══ pienet näytöt: the four pages stack on the phone's margin ═══ */
@media (max-width:860px) {
  .kavaus { padding:15vh 7vw 0; }
  .kmast { grid-template-columns:1fr; }
  .kjohd { justify-self:start; margin-top:2.6vh; padding-bottom:0; }
  .kluvut { padding:9vh 7vw 3vh; }
  .kluvut .luvut { grid-template-columns:1fr 1fr; gap:5vh 6vw; }
  .kkerros { padding:9vh 7vw 4vh; grid-template-columns:1fr;
    grid-template-areas:"paa" "logo" "sis" "aside"; }
  .kkerros:last-of-type { padding-bottom:12vh; }
  .klogo { margin-top:4.5vh; }
  .lsub { font-size:clamp(11px,2.8vw,14px); }
  .llogoH { gap:clamp(14px,4vw,24px); }
  .hmer { height:clamp(96px,24vw,140px); }
  .hnim { font-size:clamp(11px,2.8vw,14px); }
  .ksis { margin-top:4.5vh; }
  .laside { margin-top:5vh; }
  .lprint { margin-bottom:4vh; }
}

.lfaktat .ll { font-size:12px; letter-spacing:.12em; }
