@charset "UTF-8";
/* ==========================================================================
   LANTEK Computers - INTERFACE ELEMENTS
   Added 15 September 2026.

   WHY THESE ARE NOT REACT COMPONENTS, and it is not a shortcut.

   The owner asked for elements from 21st.dev and supplied one of them as a
   React file: container-scroll-animation.tsx, which wants React, framer-motion,
   Tailwind, TypeScript and a shadcn project layout. Its own instructions open
   by saying the codebase must support all four.

   This codebase is a WordPress Divi 5 child theme. Page content is generated
   into Divi Code modules as static markup; the whole front end is hand written
   CSS and one vanilla JS file. Installing React, a bundler, Tailwind and a
   TypeScript toolchain into a WordPress theme so that one card can tilt would
   add a build step, a hydration boundary and roughly 60 KB of runtime to every
   page on the site, to reproduce an effect that is nine lines of CSS.

   So each element here is rebuilt natively, to the same specification. The
   scroll container below does exactly what the supplied component does:
   rotateX 20deg to 0, scale 1.05 to 1, header translateY 0 to -100, driven by
   the element's own progress through the viewport. Same numbers, no framework.

   THREE RULES, the same ones the instruments file follows.
   1. Compositor only: transform, opacity, clip. Nothing animates layout.
   2. Off screen is off. Anything that runs is owned by an observer.
   3. prefers-reduced-motion gets the END STATE, never a blank.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. SCROLL CONTAINER
   The supplied component, natively. A card lying back in perspective that
   stands up as it enters the viewport.
   -------------------------------------------------------------------------- */
.lkfx-scroll{position:relative;perspective:1400px;padding:clamp(20px,4vw,60px) 0}
.lkfx-scroll__head{
  max-width:56ch;margin:0 auto clamp(24px,3vw,44px);text-align:center;
  transform:translateY(var(--lkfx-head,0px));
  will-change:transform;
}
.lkfx-scroll__card{
  position:relative;margin-inline:auto;max-width:1060px;
  /* The fallbacks are the END of the animation, not the start. Defaulting to
     20deg meant reduced motion and a JS failure both left the console lying
     flat on its back forever, which is the one state it must never rest in.
     scrollContainer() pushes it to 20deg when it runs; nothing else can. */
  transform:rotateX(var(--lkfx-rot,0deg)) scale(var(--lkfx-scale,1));
  transform-origin:50% 0;
  border:1px solid rgba(143,216,255,.18);border-radius:18px;
  background:linear-gradient(180deg,#0B1524,#070D18);
  padding:clamp(8px,1vw,14px);
  box-shadow:
    0 1px 0 rgba(255,255,255,.07) inset,
    0 9px 20px rgba(0,0,0,.29), 0 37px 37px rgba(0,0,0,.26),
    0 84px 50px rgba(0,0,0,.15), 0 149px 60px rgba(0,0,0,.04);
  will-change:transform;
}
.lkfx-scroll__in{border-radius:12px;overflow:hidden;background:#060B14}
@media(prefers-reduced-motion:reduce){
  .lkfx-scroll__card{transform:none}
  .lkfx-scroll__head{transform:none}
}

/* --------------------------------------------------------------------------
   2. BORDER BEAM
   A short arc of light travelling the border of a card. One element, one
   rotation, masked to the border box, so it composites and never repaints.
   -------------------------------------------------------------------------- */
.lkfx-beam{position:relative;isolation:isolate}
.lkfx-beam::before{
  content:"";position:absolute;inset:-1px;border-radius:inherit;z-index:-1;
  background:conic-gradient(from var(--lkfx-a,0deg),
    transparent 0turn,transparent .78turn,
    var(--lk-cyan) .90turn,var(--lk-ice) .96turn,transparent 1turn);
  animation:lkfx-spin 5.5s linear infinite;
}
.lkfx-beam::after{
  content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;
  background:inherit;
}
@property --lkfx-a{syntax:'<angle>';inherits:false;initial-value:0deg}
@keyframes lkfx-spin{to{--lkfx-a:360deg}}
/* Firefox has no @property, so the conic angle cannot animate there. It gets a
   static lit edge rather than a dead one. */
@supports not (background:conic-gradient(from 0deg,red,blue)){
  .lkfx-beam::before{background:linear-gradient(120deg,transparent 40%,var(--lk-cyan),transparent 70%);animation:none}
}
@media(prefers-reduced-motion:reduce){.lkfx-beam::before{animation:none}}

/* --------------------------------------------------------------------------
   3. SPOTLIGHT
   A soft light that follows the pointer across a card. Pure CSS off two
   custom properties the pointer handler writes.
   -------------------------------------------------------------------------- */
.lkfx-spot{position:relative;isolation:isolate}
.lkfx-spot::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .45s var(--lk-ease);
  background:radial-gradient(360px circle at var(--lkfx-x,50%) var(--lkfx-y,50%),
    rgba(79,180,245,.16),transparent 62%);
}
.lkfx-spot:hover::before,.lkfx-spot:focus-within::before{opacity:1}
@media(hover:none){.lkfx-spot::before{display:none}}

/* --------------------------------------------------------------------------
   4. COMPARE
   Two states of the same night, one dragged over the other. The handle is a
   real range input, so it works with a keyboard and needs no pointer code.
   -------------------------------------------------------------------------- */
.lkfx-cmp{
  position:relative;border-radius:var(--lk-r-lg);overflow:hidden;
  border:1px solid var(--lk-line);background:var(--lk-panel);
  --lkfx-split:50%;
}
.lkfx-cmp__pane{padding:clamp(22px,3vw,36px)}
/* FIXED 15 September 2026. This reserved space by tying padding to the split,
   so at 50% the left pane got 50% padding-right and its paragraph wrapped into
   a ten character ribbon. Both panes now hold a FIXED half-width column on
   their own side; the divider reveals and hides, and neither column ever
   reflows as it moves. Text does not behave like the two photographs these
   sliders are usually built for, and this is the difference. */
.lkfx-cmp__a > *{max-width:min(42ch,46%)}
/* The second pane is clipped from the left, so its CONTENT has to live to
   the right of the split or the reveal shows an empty box. This is the
   difference between comparing two photographs, where both sides are the same
   picture and clipping just swaps which one you see, and comparing two pieces
   of TEXT, where the words have to be inside the part you are revealing.
   Shipped once without this and the right half was blank at every position. */
.lkfx-cmp__b{
  position:absolute;inset:0;
  clip-path:inset(0 0 0 var(--lkfx-split));
  padding-left:52%;
}
.lkfx-cmp__line{
  position:absolute;top:0;bottom:0;left:var(--lkfx-split);width:2px;
  background:var(--lk-cyan);box-shadow:0 0 18px rgba(32,187,252,.8);
  pointer-events:none;
}
.lkfx-cmp__grip{
  position:absolute;top:50%;left:var(--lkfx-split);
  width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;
  background:var(--lk-cyan);box-shadow:0 0 22px rgba(32,187,252,.85);
  display:grid;place-items:center;pointer-events:none;color:#04060B;
}
.lkfx-cmp__grip svg{width:18px;height:18px}
.lkfx-cmp input[type=range]{
  position:absolute;inset:0;width:100%;height:100%;margin:0;
  opacity:0;cursor:ew-resize;
}
.lkfx-cmp input[type=range]:focus-visible{opacity:0}
.lkfx-cmp:focus-within .lkfx-cmp__line{box-shadow:0 0 0 3px rgba(143,216,255,.45),0 0 18px rgba(32,187,252,.8)}
/* Above both panes. Pane B is position:absolute with its own background and
   was painting straight over the right hand tag. */
.lkfx-cmp__tag{
  position:absolute;top:14px;z-index:4;font-size:10.5px;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;
  padding:5px 10px;border-radius:99px;background:rgba(4,6,11,.72);
}
.lkfx-cmp__tag--a{left:14px;color:var(--lk-ink-3)}
.lkfx-cmp__tag--b{right:14px;color:var(--lk-ice)}

/* --------------------------------------------------------------------------
   5. TEXT REVEAL
   A statement that resolves word by word as it crosses the viewport. Each
   word is its own span; only opacity moves.
   -------------------------------------------------------------------------- */
.lkfx-reveal{color:var(--lk-ink-4)}
.lkfx-reveal w{display:inline-block;color:#fff;opacity:.16;transition:opacity .5s var(--lk-ease)}
.lkfx-reveal w.is-lit{opacity:1}
@media(prefers-reduced-motion:reduce){.lkfx-reveal w{opacity:1;transition:none}}

/* --------------------------------------------------------------------------
   6. TILT
   A card that leans toward the pointer. Two custom properties, one transform.
   -------------------------------------------------------------------------- */
.lkfx-tilt{
  transform:perspective(900px) rotateX(var(--lkfx-rx,0deg)) rotateY(var(--lkfx-ry,0deg));
  transition:transform .5s var(--lk-ease);will-change:transform;
}
.lkfx-tilt:hover{transition:transform .12s linear}
@media(hover:none),(prefers-reduced-motion:reduce){.lkfx-tilt{transform:none}}

/* --------------------------------------------------------------------------
   7. TABS
   A sliding indicator under a row of real buttons.
   -------------------------------------------------------------------------- */
.lkfx-tabs{position:relative;display:flex;gap:4px;flex-wrap:wrap;
  border-bottom:1px solid var(--lk-line-2);padding-bottom:0}
.lkfx-tab{
  appearance:none;background:none;border:0;cursor:pointer;
  padding:10px 14px 13px;font:inherit;font-size:13.5px;font-weight:500;
  color:var(--lk-ink-3);transition:color var(--lk-fast) var(--lk-ease);
}
.lkfx-tab:hover{color:var(--lk-ink)}
.lkfx-tab[aria-selected="true"]{color:#fff}
.lkfx-tabs__ind{
  position:absolute;bottom:-1px;height:2px;border-radius:2px;
  background:var(--lk-cyan);box-shadow:0 0 12px rgba(32,187,252,.9);
  transform:translateX(var(--lkfx-tx,0px));width:var(--lkfx-tw,0px);
  transition:transform .42s var(--lk-ease),width .42s var(--lk-ease);
}
@media(prefers-reduced-motion:reduce){.lkfx-tabs__ind{transition:none}}
.lkfx-panel[hidden]{display:none}

/* --------------------------------------------------------------------------
   8. TIMELINE
   A vertical rule that draws itself as the list scrolls past.
   -------------------------------------------------------------------------- */
.lkfx-time{position:relative;padding-left:clamp(26px,3vw,40px)}
.lkfx-time::before{
  content:"";position:absolute;left:7px;top:6px;bottom:6px;width:1px;
  background:var(--lk-line-2);
}
.lkfx-time__fill{
  position:absolute;left:7px;top:6px;width:1px;
  background:linear-gradient(180deg,var(--lk-cyan),var(--lk-blue));
  height:var(--lkfx-fill,0%);
  box-shadow:0 0 10px rgba(32,187,252,.7);
}
.lkfx-time__i{position:relative;padding:0 0 clamp(22px,2.6vw,34px)}
.lkfx-time__i:last-child{padding-bottom:0}
.lkfx-time__i::before{
  content:"";position:absolute;left:calc(-1 * clamp(26px,3vw,40px) + 3px);top:6px;
  width:9px;height:9px;border-radius:50%;
  background:var(--lk-panel);border:1px solid var(--lk-line-3);
}
.lkfx-time__i.is-on::before{background:var(--lk-cyan);border-color:var(--lk-cyan);
  box-shadow:0 0 11px rgba(32,187,252,.9)}
.lkfx-time__t{font-family:var(--lk-mono);font-size:11px;letter-spacing:.08em;color:var(--lk-sky)}
.lkfx-time__h{margin-top:4px;font-size:15.5px;font-weight:600;letter-spacing:-.02em;color:#fff}
.lk .lkfx-time__d{margin-top:5px;font-size:14px;line-height:1.55;color:var(--lk-ink-2);max-width:56ch}

/* --------------------------------------------------------------------------
   9. DIVIDER
   A hairline with a slow travelling highlight. Marks the seam between two
   sections without drawing a box around anything.
   -------------------------------------------------------------------------- */
.lkfx-rule{
  position:relative;height:1px;width:100%;border:0;margin:0;
  background:var(--lk-line-2);overflow:hidden;
}
.lkfx-rule::after{
  content:"";position:absolute;top:0;left:0;height:100%;width:34%;
  background:linear-gradient(90deg,transparent,var(--lk-cyan),transparent);
  animation:lkfx-slide 7s var(--lk-ease) infinite;
}
@keyframes lkfx-slide{0%{transform:translateX(-100%)}60%,100%{transform:translateX(400%)}}
@media(prefers-reduced-motion:reduce){.lkfx-rule::after{animation:none;opacity:.35}}

/* --------------------------------------------------------------------------
   10. MAGNETIC
   A button that leans a few pixels toward the cursor. Small on purpose: the
   effect is meant to be felt rather than watched.
   -------------------------------------------------------------------------- */
.lkfx-mag{
  transform:translate3d(var(--lkfx-mx,0px),var(--lkfx-my,0px),0);
  transition:transform .42s var(--lk-ease);will-change:transform;
}
.lkfx-mag:hover{transition:transform .1s linear}
@media(hover:none),(prefers-reduced-motion:reduce){.lkfx-mag{transform:none}}

/* --------------------------------------------------------------------------
   THE TWO NIGHTS
   The panes inside the compare slider. Both are the same size and the same
   shape on purpose: the only thing that should read as different between them
   is what actually happened.
   -------------------------------------------------------------------------- */
.lkh-night{min-height:clamp(230px,24vw,290px);display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.lkh-night--a{background:linear-gradient(160deg,#0A0E17,#070A11)}
.lkh-night--b{background:linear-gradient(160deg,#0B1A2C,#071320)}
.lkh-night__h{
  font-family:var(--lk-mono);font-size:12px;letter-spacing:.1em;
  color:var(--lk-ink-4);
}
.lkh-night--b .lkh-night__h{color:var(--lk-sky)}
.lk .lkh-night__d{font-size:15px;line-height:1.6;color:var(--lk-ink-2);max-width:42ch;margin:0}
.lkh-night__s{
  margin-top:auto;font-size:11px;font-weight:600;letter-spacing:.11em;
  text-transform:uppercase;padding:6px 12px;border-radius:99px;border:1px solid;
}
.lkh-night__s--bad{color:var(--lk-hot);border-color:rgba(255,90,71,.4);background:rgba(255,90,71,.09)}
.lkh-night__s--good{color:var(--lk-ok);border-color:rgba(31,191,143,.4);background:rgba(31,191,143,.09)}

/* The right pane is clipped over the left, so it has to sit exactly on top of
   it rather than below it in the flow. */
.lkfx-cmp__b{position:absolute;inset:0}

.lk .lkh-fine{
  margin-top:clamp(26px,3vw,40px);font-size:13px;line-height:1.55;
  color:var(--lk-ink-4);max-width:66ch;
}

@media(max-width:620px){
  .lkh-night{min-height:clamp(280px,52vw,340px)}
  .lk .lkh-night__d{font-size:14px}
}

/* The console when it is inside the scroll container: it takes its rotation
   from the scroll progress, so its own static tilt has to come off or the two
   transforms fight and the panel skews. */
.lkh-ui--scroll{transform:rotateX(var(--lkfx-rot,0deg)) scale(var(--lkfx-scale,1));transform-origin:50% 0;margin-inline:auto;max-width:none}
@media(min-width:900px){.lkh-ui--scroll{margin-right:0}}

/* The NIST tabs sit above the table, not in their own row of the grid. */
.lkh-nist__tabs{margin-bottom:clamp(18px,2vw,26px)}

/* The NIST column: tabs above the table, both inside one grid cell. */
.lkh-nist__col{min-width:0}

/* On one column the compare stacks instead of splitting. A 50% clip on a
   390px screen leaves 195px for a paragraph, which is not a comparison, it is
   two ribbons. Below 760px the divider goes and both nights are simply shown,
   one after the other, which is what the section is actually saying. */
@media(max-width:760px){
  .lkfx-cmp{--lkfx-split:0%}
  .lkfx-cmp__b{position:static;clip-path:none;padding-left:clamp(22px,3vw,36px);
    border-top:1px solid var(--lk-line-3)}
  .lkfx-cmp__a > *{max-width:none}
  .lkfx-cmp__line,.lkfx-cmp__grip,.lkfx-cmp input[type=range]{display:none}
  .lkfx-cmp__tag{position:static;display:inline-block;margin-bottom:12px}
  .lkfx-cmp__tag--b{margin-top:0}
}

/* --------------------------------------------------------------------------
   THE PHONE LEGIBILITY FLOOR
   The same floor lantek-home.css applies, for the interface elements. A tag
   or a timestamp set at 10.5px reads as a texture on a phone rather than as
   a word, and both of these carry meaning the reader needs.
   -------------------------------------------------------------------------- */
@media(max-width:640px){
  .lkfx-cmp__tag{font-size:11.5px;letter-spacing:.05em}
  .lkfx-time__t{font-size:12px}
}
