/* ============================================================
   ABR Forex Trading — landing
   Built to the reference Ghady supplied on 2026-09-11: black
   ground, the mark centred, the full name in gold under it, a
   row of four facts, one CONTACT action, and the bar motif
   rising across the foot of the screen. The white section in
   that reference was dropped on his instruction.

   Tunables are --k- properties, same contract as the mocks, so
   the design lab can drive this page too.
   ============================================================ */
:root{
  /* ---- palette, sampled from the supplied logo ---- */
  --k-black:#000000;
  --k-gold:#e1a84e;
  --k-gold-light:#f3d96a;
  --k-gold-deep:#b59250;
  --k-bone:#f2efe8;

  /* ---- the wordmark ---- */
  --k-name:5.3;           /* vw */
  --k-name-max:6.6;       /* rem cap */
  --k-name-wght:800;
  --k-name-wdth:104;
  --k-name-track:.005;    /* em */

  /* ---- the mark ---- */
  --k-mark:20.5;          /* vw */
  --k-mark-max:300;       /* px cap */
  --k-mark-vh:33;         /* svh cap: a short laptop is the case that overflows,
                             and the mark is the tallest thing in the stack */

  /* ---- chrome ---- */
  --k-nav:15;             /* px */
  --k-facts:13;           /* px */
  --k-facts-w:76;         /* vw, how wide the five facts spread */
  --k-horizon:20;         /* vh. The band at the foot of the screen, and the
                             bar motif is exactly that band: it cannot reach up
                             into the CONTACT button because the band is the
                             hero's bottom padding, so the content never enters
                             it. Widen the motif by growing this. */
  --k-rig-x:0;            /* % of the rig's own width, if it ever needs nudging
                             sideways. The art is centred at 0. */

  /* How far down the hero starts. --hero-top is the DESIGNED distance and it
     is the approved one, untouched. --nav-ink is where the nav's actual type
     and button end, measured and published by site.js, and it is used only as
     a floor: the padding is whichever is larger. So the composition is exactly
     as approved wherever there is room, and the mark is pushed clear only on
     the screens where it would otherwise sit under the nav. The nav's own box
     is no use for this, because its padding leaves 20-odd px of empty space
     below the ink that the mark is perfectly entitled to use. */
  /* Lowered from clamp(100px,14.2vh,158px) on 2026-09-13: Ghady, looking at
     1920x1080, "Logo and ABR Forex trading with the icons should be higher a
     bit". This is a design change he asked for, not a fix dressed as one. The
     nav floor below is what keeps it safe: at every size the measured nav ink
     is 8 to 35px under the old value, so the composition moves up only where
     there is genuinely room and is held off the nav everywhere else. */
  --hero-top:clamp(88px,12.2vh,136px);
  --hero-safe:clamp(8px,1.4vh,16px);   /* least air allowed under the nav ink */
  --k-hero-gap:7;         /* vh. The air under the CONTACT button, between it and
                             the top of the foot band. It is a measure, not a
                             remainder: the button sits this far above the band
                             and every other spare pixel opens up above it,
                             between the icons and the button. It can shrink on
                             a screen with no room to spare, never grow. */
  --hero-gap:min(max(calc(var(--k-hero-gap) * 1vh),44px),96px);
  --k-hero-lift:8;        /* vh. The most the gap between the icons and the
                             CONTACT button opens by. Without a cap a tall
                             screen hands it everything: 236px at 834x1112,
                             which strands the button in the middle of nowhere
                             and is the same fault as the void, moved. */
  --hero-lift:min(max(calc(var(--k-hero-lift) * 1vh),48px),110px);
  --k-band-min:150;       /* px. The floor under the band, so the motif is
                             never a sliver on a narrow screen. It has to come
                             down on a short one, or 150px of a 390px-tall
                             landscape phone is spent on the foot. */

  /* One number the band, the hero's bottom padding, the motif and the lit
     ground line all read, so they cannot drift apart. Capped against the
     viewport width, so a wide motif never pushes a phone sideways. */
  --band-h:min(max(calc(var(--k-horizon) * 1vh),calc(var(--k-band-min) * 1px)),
               calc(96vw * 176 / 478));
  --k-glow:1;             /* how much glow the gold carries; 0 = flat */

  /* ---- the channel section ---------------------------------------
     The wall is generated from these rather than hand-placed, so the
     curve is one thing to tune instead of seven transforms to keep in
     step. Each card carries an index --i and reads its angle, depth and
     spacing from here. */
  --k-ch-title:5.6;       /* vw */
  --k-ch-title-max:5.4;   /* rem cap */
  --k-wall-h:430;         /* px, the stage the arc stands on */
  --k-wall-p:2200;        /* px of perspective; lower is a harder angle */
  --k-wall-r:1000;         /* px, the radius of the cylinder the cards sit on.
                             Capped against the viewport so the arc can never
                             be wider than the screen it is drawn on. */
  --k-wall-spread:9;      /* deg between cards around that cylinder */
  --k-wall-pingap:3;      /* deg of extra room either side of the pinned card, which is wider */
  --k-wall-tuck:.24;      /* share of its own width an outer card keeps empty where
                             it tucks under its inner neighbour. Measured, not
                             guessed: at .19 the outermost labels were covered by
                             three or four pixels above about 2100px wide and
                             under a hard cursor turn. .24 clears every width
                             from 1101 to 2560 and the full turn range. */
  --k-wall-face:.9;       /* how much of its arc angle each card actually turns
                             through. 1 pivots it fully, which puts its inner edge
                             in front of its neighbour's and makes the depth sort
                             a coin toss; below about .92 the sort is decisive and
                             the fan always paints from the middle outwards. Lower
                             flattens the cards toward the screen and widens the
                             overlap, so the tuck has to follow it down. */
  --k-wall-tilt:2;        /* deg, the whole wall leaning back */
  --k-wall-react:1;       /* how hard the wall answers the cursor; 0 = still */
  --k-wall-drift:1;       /* the slow breath it keeps when no cursor is there */
  --k-card-w:206;         /* px, the widest a message card gets */
  --k-card-pin:292;       /* px, the widest the pinned card gets; it leads */

  /* ---- plate, the card material: one definition --------------------
     Ghady picked plate for the channel on 2026-09-12, and the Academy uses
     the same material so the site reads as one system. The channel's cards
     and the Academy's both read these, so the two cannot drift apart: a
     brushed dark face, one corner cut at the diamond's own angle, and the
     edge lit on the two sides the light comes from. */
  --plate-cut:20px;
  --plate-clip:polygon(0 0,calc(100% - var(--plate-cut)) 0,100% var(--plate-cut),100% 100%,0 100%);
  --plate-face:linear-gradient(100deg,rgba(255,255,255,.05),transparent 38%),
    repeating-linear-gradient(92deg,#111114 0 2px,#0d0d10 2px 4px);
  --plate-edge:linear-gradient(180deg,rgba(243,217,106,.5),transparent 2px),
    linear-gradient(90deg,rgba(225,168,78,.36),transparent 2px);
  --plate-shadow:0 30px 58px rgba(0,0,0,.72);

  /* ---- gold type: one definition ------------------------------------
     The standing vertical gold and the one light that travels across it.
     The landing's name and the Academy's both read these. */
  --type-gold:linear-gradient(177deg,#fbe9a6 2%,var(--k-gold-light) 24%,
    var(--k-gold) 56%,#c98f34 84%,var(--k-gold-deep));
  --type-sweep:linear-gradient(100deg,rgba(255,246,214,0) 41%,
    rgba(255,248,222,.92) 50%,rgba(255,246,214,0) 59%);

  /* ---- about ------------------------------------------------------
     05 Emblem's About: one huge paragraph across the width, the biography
     set to the right, a row of three photographs. The paragraph's own
     five pillars are set four ways while Ghady picks (data-abhl). */
  --k-about-fs:3.6;       /* vw, the paragraph */
  --k-about-fs-min:24;    /* px floor, so a phone still reads it as the statement */
  --k-about-fs-max:3.5;   /* rem cap */
  --k-about-ph:.8;        /* photo frame shape, width over height (4:5) */

  /* ---- the academy ------------------------------------------------ */
  /* ---- feedback ---------------------------------------------------
     One fan, and a switch between the two categories. The frame is portrait
     because the content is phone screenshots. */
  --k-fb-ratio:.62;       /* frame width as a share of its height */
  --k-fan-h:430;          /* px, the front card's height in the fan layout */
  --k-fan-spread:150;     /* px between card centres along the fan */
  --k-fan-angle:8;        /* deg each card turns per step out from the front */
  --k-fan-drop:26;        /* px a card sinks for its first step; the arc steepens after */
  --k-fan-shrink:.07;     /* how much smaller a card is per step */
  --k-fan-open:1.12;      /* the spread multiplier while the pointer is on the fan */
  --k-off-chjoin-x:0;      --k-off-chjoin-y:0;
  --k-off-fbtitle-x:0;     --k-off-fbtitle-y:0;
  --k-off-fbcommunity-x:0; --k-off-fbcommunity-y:0;
  --k-off-fbfan-x:0;       --k-off-fbfan-y:0;

  --k-ac-title:7;         /* vw, ABR ACADEMY with the cards below it */
  --k-ac-title-side:4.4;  /* vw, the same with the cards either side, where
                             the name has to share its row */
  --k-ac-title-max:6.8;   /* rem cap */
  --k-ac-mark:13;         /* vw; smaller than the landing's, so the hero leads */
  --k-ac-mark-max:210;    /* px cap */
  --k-lvl-w:420;          /* px, the widest a level card gets */
  --k-lvl-lift:6;         /* px, how far a level card rises under the pointer */
  --k-win-w:820;          /* px, the widest a level window gets */
  --k-credits:46;         /* seconds for one full pass of the credits */
  --k-credits-fs:24;      /* px, the topic type in the credits */
  --k-credits-op:.3;      /* how far back the credits sit; 0 hides them. At .5
                             the first render read as a wall of grey type down
                             both sides, louder than the cards it stands behind */

  /* ---- motion -----------------------------------------------------
     Two dials drive the whole entrance, so the timing can be tuned in
     the lab instead of guessed at in a note. --k-anim multiplies every
     duration and delay on the page (.6 is brisk, 1.6 is slow and
     deliberate); --k-stagger is the gap between items in a run. Both
     are read by the script too, so the mark's arrival in 3D keeps step
     with the CSS rather than drifting off it. */
  --k-anim:1;
  --k-stagger:60;         /* ms between staggered items */
  --k-sheen:7.5;          /* seconds for one pass of the light across the name */

  /* ---- placement ------------------------------------------------
     Every block on the page can be nudged in pixels without touching the
     layout. site/lab writes these by dragging; the numbers it hands back
     paste straight in here. All zero is the designed position. */
  --k-off-lock-x:0;  --k-off-lock-y:0;
  --k-off-menu-x:0;  --k-off-menu-y:0;
  --k-off-pill-x:0;  --k-off-pill-y:0;
  --k-off-mark-x:0;  --k-off-mark-y:0;
  --k-off-name-x:0;  --k-off-name-y:0;
  --k-off-facts-x:0; --k-off-facts-y:0;
  --k-off-cta-x:0;   --k-off-cta-y:0;
  --k-off-foot-x:0;  --k-off-foot-y:0;
  --k-off-wall-x:0;  --k-off-wall-y:0;
  --k-off-acmark-x:0;  --k-off-acmark-y:0;
  --k-off-actitle-x:0; --k-off-actitle-y:0;
  --k-off-accards-x:0; --k-off-accards-y:0;
  --k-off-credits-x:0; --k-off-credits-y:0;
  --k-off-abeyebrow-x:0; --k-off-abeyebrow-y:0;
  --k-off-abtext-x:0;    --k-off-abtext-y:0;
  --k-off-abaside-x:0;   --k-off-abaside-y:0;
  --k-off-abphotos-x:0;  --k-off-abphotos-y:0;

  --sans:'Archivo',system-ui,-apple-system,sans-serif;
  --gutter:clamp(16px,3.4vw,54px);
  --ease:cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{background:var(--k-black);color:var(--k-bone);font-family:var(--sans);
  overflow-x:clip;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:inherit;text-decoration:none}
/* canvas is block too, and that is not cosmetic: left inline it sits on a
   text baseline, which adds a 3px descender inside #markwrap. fit() then
   reads the taller box, resizes the renderer to it, and the wrapper grows
   again on the next frame. The hero grew without bound in live mode. */
img,svg,canvas{display:block;max-width:100%}
:focus-visible{outline:2px solid var(--k-gold);outline-offset:3px}

/* the live ground: a slow field behind everything, never in front of it */
#bg{position:fixed;inset:0;width:100%;height:100%;z-index:0;display:block}

/* ================= nav ================= */
.nav{position:fixed;top:0;left:0;right:0;z-index:20;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px;
  padding:clamp(16px,2.4vh,26px) var(--gutter)}
/* The nav is transparent over the hero, which is right: it sits on the live
   ground and the mark lights it. The moment a second section exists that is
   no longer safe, because the page scrolls under it and the channel's cards
   ran straight through the wordmark. It takes a ground of its own as soon as
   the hero is left, and gives it back at the top. */
.nav::before{content:"";position:absolute;inset:0;z-index:-1;
  background:rgba(0,0,0,.82);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(225,168,78,.16);
  opacity:0;transition:opacity .4s var(--ease)}
.scrolled .nav::before{opacity:1}
.lockup{display:flex;align-items:center;gap:13px}
.lockup{translate:calc(var(--k-off-lock-x) * 1px) calc(var(--k-off-lock-y) * 1px)}
/* The chrome arrives too. It used to be fully drawn in the first frame,
   so the page opened with its nav and its mark already finished and only
   the name moving. Wiped in from the left, and the transform is separate
   from the lab's `translate` so the two compose instead of fighting. */
.lockup{clip-path:inset(-30% 100% -30% 0);transform:translateX(-16px);
  transition:clip-path calc(.95s * var(--k-anim)) calc(.06s * var(--k-anim)) var(--ease),
             transform calc(.95s * var(--k-anim)) calc(.06s * var(--k-anim)) var(--ease)}
.in .lockup,.still .lockup{clip-path:inset(-30% 0 -30% 0);transform:none}
.lockup .mk{width:clamp(44px,4.7vw,70px);flex:none}
.lockup .mk img{width:100%;height:auto}
.lockup .wm{line-height:1}
.lockup .wm b{display:block;font-size:clamp(17px,1.82vw,27px);font-weight:800;
  font-variation-settings:'wdth' 108;letter-spacing:.055em;
  background:linear-gradient(180deg,var(--k-gold-light),var(--k-gold) 55%,var(--k-gold-deep));
  -webkit-background-clip:text;background-clip:text;color:transparent}
.lockup .wm i{display:block;font-style:normal;font-size:clamp(8.5px,.78vw,11.5px);
  font-weight:600;letter-spacing:.44em;text-transform:uppercase;
  color:var(--k-gold-deep);margin-top:3px}

.menu{display:flex;gap:clamp(18px,2.8vw,46px);justify-content:center;flex-wrap:wrap}
.menu{translate:calc(var(--k-off-menu-x) * 1px) calc(var(--k-off-menu-y) * 1px)}
/* A nav link is a tap target before it is a word, and as the text alone it was
   19px tall on every phone: under the 24px WCAG floor, far under the 44px a
   thumb actually wants. --hit is the invisible half of it, added as padding and
   taken straight back as a negative margin, so the row does not move by a pixel
   and only the hit area grows. Vertically only: negative side margins would eat
   into the flex gap and run the words together. */
.menu a{--hit:12px;
  font-size:calc(var(--k-nav) * 1px);font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--k-bone);opacity:.82;
  padding:var(--hit) 0 calc(7px + var(--hit));margin-block:calc(var(--hit) * -1);
  position:relative;transition:opacity .25s,color .25s;
  /* The mask the word rises into used to be overflow:clip on this box, which is
     why the box could never be bigger than the word: pad it and the word parked
     below became visible inside the padding. The mask is on the word itself now,
     as a clip, which is what the facts row and the CONTACT button already do. */
  display:inline-block}
/* One word per link, each rising behind its own mask on its own beat.
   The span moves, the link does not, so the underline stays anchored. */
.menu a > span{display:block;transform:translateY(150%);
  /* starts past the bleed rather than flush with the edge, or a glow shows as
     a one pixel line before the word arrives */
  clip-path:inset(calc(100% + 4px) -2px -4px -2px);
  transition:transform calc(.8s * var(--k-anim)) var(--d,0ms) var(--ease),
             clip-path calc(.8s * var(--k-anim)) var(--d,0ms) var(--ease)}
.in .menu a > span,.still .menu a > span{transform:none;
  clip-path:inset(-4px -2px -4px -2px)}
.menu a:nth-child(1){--d:calc(var(--k-stagger) * 2ms * var(--k-anim))}
.menu a:nth-child(2){--d:calc(var(--k-stagger) * 3ms * var(--k-anim))}
.menu a:nth-child(3){--d:calc(var(--k-stagger) * 4ms * var(--k-anim))}
.menu a:nth-child(4){--d:calc(var(--k-stagger) * 5ms * var(--k-anim))}
/* bottom is --hit, not 0, so the underline stays exactly 7px under the word
   however much invisible tap area the link is carrying */
.menu a::after{content:"";position:absolute;left:50%;right:50%;bottom:var(--hit);height:1.5px;
  background:var(--k-gold);transition:left .3s var(--ease),right .3s var(--ease)}
.menu a:hover{opacity:1;color:var(--k-gold-light)}
.menu a:hover::after,.menu a[aria-current="page"]::after{left:0;right:0}
.menu a[aria-current="page"]{opacity:1;color:var(--k-gold)}

.nav > .pill{translate:calc(var(--k-off-pill-x) * 1px) calc(var(--k-off-pill-y) * 1px)}
/* The pill draws itself in from its own edge, the ring arriving with the
   word inside it, so the last thing to land in the chrome is the thing you
   click. A wipe and not a fade: the rule against fading type is not only
   about the headline, and a stalled fade on the one action is worse than a
   stalled fade anywhere else. */
/* the insets stay negative on three sides so the ring's own glow is never
   cropped; only the left edge moves, sweeping the reveal right to left */
.nav > .pill{clip-path:inset(-60% -60% -60% 101%);
  transition:clip-path calc(.85s * var(--k-anim)) calc(.32s * var(--k-anim)) var(--ease),
             background .3s,box-shadow .3s,color .3s}
.in .nav > .pill,.still .nav > .pill{clip-path:inset(-60% -60% -60% -60%)}
.pill{justify-self:end;display:inline-block;font-size:calc(var(--k-nav) * 1px);
  font-weight:600;letter-spacing:.18em;text-transform:uppercase;white-space:nowrap;
  padding:clamp(13px,1.9vh,19px) clamp(26px,3.4vw,50px);
  border:1px solid var(--k-gold);border-radius:999px;color:var(--k-bone);
  background:radial-gradient(120% 160% at 50% 130%,rgba(225,168,78,.22),transparent 62%);
  box-shadow:0 0 calc(26px * var(--k-glow)) -6px rgba(225,168,78,.55),
             inset 0 0 calc(18px * var(--k-glow)) -10px rgba(243,217,106,.7);
  transition:background .3s,box-shadow .3s,color .3s}
.pill:hover{color:#141008;background:var(--k-gold);
  box-shadow:0 0 calc(40px * var(--k-glow)) -4px rgba(225,168,78,.8)}

/* ================= hero ================= */
main{position:relative;z-index:1}
.hero{min-height:100svh;display:flex;flex-direction:column;align-items:center;
  /* Once both spacers below have reached their caps there can still be height
     left over, on a screen far taller than the stack. That last remainder is
     split evenly above and below rather than dumped at one end, so the
     composition centres instead of hanging. safe, because a viewport too short
     for the stack has to overflow downward where it can still be scrolled to,
     never upward under the fixed nav. */
  justify-content:flex-start;justify-content:safe center;
  padding:max(var(--hero-top),calc(var(--nav-ink,0px) + var(--hero-safe)))
          var(--gutter) calc(var(--band-h) + 8px);
  position:relative;text-align:center}
/* Where the slack goes. The hero is one screen by contract and the stack
   rarely fills it, so there is height left over and it has to be put
   somewhere. There are only three places: above the mark, between the icons
   and the action, and under the action.

   Two of those are wrong. Above the mark pushes the whole composition down
   the screen. Under the action leaves a void and strands the button in the
   middle of nowhere, which is how this shipped and what Ghady called on
   2026-09-13: 11px of air above the logo and 105px of nothing under CONTACT
   at 1920x1080.

   So all of it goes in the third place. The action keeps a fixed measure of
   air under it (--hero-gap, which can shrink but not grow), and everything
   else opens up between the icons and the button: the logo, the name and the
   facts stay hard against the top of the screen, and the action moves down
   toward the band and reads as an action rather than as a fifth fact.

   The spacer is ::before given an order, so there is still only one element
   doing it and it sits where it is needed.

   Both spacers have a flex-basis of 0, so neither of them can ever ADD to the
   hero's height: give the lower one a real basis and a screen with no room to
   spare grows past one viewport instead of shrinking the gap, which put the
   hero 24 to 53px over the screen at five sizes on the first attempt. The
   lower one fills first, up to --hero-gap, so the button always keeps its air
   above the band; the upper one then takes everything that is left. */
.hero::before,.hero::after{content:"";display:block;width:0;min-height:0;flex:1 1 0}
.hero::before{order:1;max-height:var(--hero-lift)}
.cta{order:2}
.hero::after{order:3;flex-grow:400;max-height:var(--hero-gap)}

/* the mark, a real object rather than a picture of one */
#markwrap{width:min(calc(var(--k-mark) * 1vw),calc(var(--k-mark-max) * 1px),
                    calc(var(--k-mark-vh) * 1svh));
  aspect-ratio:1;position:relative;z-index:2;flex:none;overflow:hidden;
  translate:calc(var(--k-off-mark-x) * 1px) calc(var(--k-off-mark-y) * 1px);
  margin-bottom:clamp(4px,.9vh,14px)}
#mark{width:100%;height:100%}
/* no WebGL: the traced vector stands in, so the mark is never missing */
.mkfall{display:none;width:100%;height:100%}
.no-gl #mark{display:none}
.no-gl .mkfall{display:block}

/* the name. Clip and transform on the entrance, never opacity:
   mid-fade gold on black fails contrast and a stalled fade leaves
   the headline invisible. */
.name{position:relative;z-index:2;overflow:hidden;padding-bottom:.08em;
  translate:calc(var(--k-off-name-x) * 1px) calc(var(--k-off-name-y) * 1px)}
.name span{display:block;
  font-size:min(calc(var(--k-name) * 1vw),calc(var(--k-name-max) * 1rem));
  font-weight:var(--k-name-wght);
  font-variation-settings:'wdth' var(--k-name-wdth);
  letter-spacing:calc(var(--k-name-track) * 1em);
  line-height:1;text-transform:uppercase;white-space:nowrap;
  /* two layers, both clipped to the glyphs: the standing vertical gold,
     and one continuous light travelling across the line. One light, not a
     per-letter flicker, because he rejected the stepped version. */
  background-image:var(--type-sweep),var(--type-gold);
  background-size:280% 100%,100% 100%;
  background-repeat:no-repeat,no-repeat;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  text-shadow:0 0 calc(30px * var(--k-glow)) rgba(203,148,58,.30);
  animation:sheen calc(var(--k-sheen) * 1s) linear infinite;
  transform:translateY(108%);
  transition:transform calc(1.05s * var(--k-anim)) calc(.5s * var(--k-anim)) var(--ease)}
.in .name span,.still .name span{transform:none}
@keyframes sheen{from{background-position:200% 0,0 0}to{background-position:-110% 0,0 0}}
body.still .name span{animation:none;background-position:56% 0,0 0}

/* the four facts, all of them things the client already told us */
.facts{position:relative;z-index:2;display:flex;align-items:stretch;flex-wrap:wrap;
  justify-content:center;margin-top:clamp(16px,2.9vh,32px);
  translate:calc(var(--k-off-facts-x) * 1px) calc(var(--k-off-facts-y) * 1px)}
/* 76vw is the designed width and it is right on a desktop, but below about
   1118px it is narrower than the five labels need, and a flex row answers that
   by wrapping: two rows with no gap between them, the second row's icons
   landing on the first row's labels, and a divider rule left hanging at the
   start of the second row. It was broken from 740px to 1100px wide, which is
   every tablet in landscape and every half-screen laptop window. A floor under
   the width keeps them on one row down to where one row genuinely stops
   fitting, and min(100%) still means it can never be wider than the hero.
   Written when there were five facts; since 2026-09-15 there are four. */
.facts{width:min(100%,max(calc(var(--k-facts-w) * 1vw),880px))}
/* Four items on four beats, not one block fading in together. The label is
   type, so this is a wipe and a rise, never an opacity fade. */
.facts .f{display:flex;flex-direction:column;align-items:center;gap:clamp(8px,1.25vh,13px);
  padding:0 clamp(14px,2vw,30px);position:relative;flex:1 1 auto;
  clip-path:inset(0 0 100% 0);transform:translateY(14px);
  transition:clip-path calc(.8s * var(--k-anim)) var(--d,0ms) var(--ease),
             transform calc(.8s * var(--k-anim)) var(--d,0ms) var(--ease)}
.in .facts .f,.still .facts .f{clip-path:inset(0 0 -30% 0);transform:none}
.facts .f:nth-child(1){--d:calc(var(--k-stagger) * 10ms * var(--k-anim))}
.facts .f:nth-child(2){--d:calc(var(--k-stagger) * 11ms * var(--k-anim))}
.facts .f:nth-child(3){--d:calc(var(--k-stagger) * 12ms * var(--k-anim))}
.facts .f:nth-child(4){--d:calc(var(--k-stagger) * 13ms * var(--k-anim))}
/* the rules between them draw from the middle out, on their item's beat */
.facts .f + .f::before{content:"";position:absolute;left:0;top:-4%;bottom:-4%;width:1px;
  background:linear-gradient(180deg,rgba(225,168,78,.05),rgba(225,168,78,.5) 45%,rgba(225,168,78,.05));
  transform:scaleY(0);
  transition:transform calc(.9s * var(--k-anim)) calc(var(--d,0ms) + .12s * var(--k-anim)) var(--ease)}
.in .facts .f + .f::before,.still .facts .f + .f::before{transform:scaleY(1)}
.facts svg{width:clamp(22px,1.95vw,29px);height:auto;stroke:var(--k-gold);
  stroke-width:1.5;fill:none;stroke-linecap:round;stroke-linejoin:round;
  transition:stroke .35s,transform .35s var(--ease)}
/* the facts are the only things on the screen that say what this is,
   so they answer the pointer. The icon lifts and lights; the label holds
   still, because moving type under a cursor is noise. */
@media (hover:hover){
  .facts .f:hover svg{stroke:var(--k-gold-light);transform:translateY(-3px)}
  .facts .f:hover .t{opacity:1}
}
.facts .t{font-size:calc(var(--k-facts) * 1px);font-weight:500;letter-spacing:.19em;
  text-transform:uppercase;color:var(--k-bone);opacity:.92;white-space:nowrap}
.facts .t.lc{text-transform:none;letter-spacing:.1em}

/* the action lands last, rising into place. Again a clip and a transform
   and no opacity, because the word inside it is type like any other. */
/* The action is not another fact, and at 28px under the icons it read as one.
   This is the least it stands apart by; the spacer above adds whatever the
   screen has spare on top of it. */
.cta{position:relative;z-index:2;margin-top:clamp(24px,4.2vh,46px);
  translate:calc(var(--k-off-cta-x) * 1px) calc(var(--k-off-cta-y) * 1px);
  clip-path:inset(101% -70% -70% -70%);transform:translateY(16px);
  transition:clip-path calc(.9s * var(--k-anim)) calc(1.02s * var(--k-anim)) var(--ease),
             transform calc(.9s * var(--k-anim)) calc(1.02s * var(--k-anim)) var(--ease)}
.in .cta,.still .cta{clip-path:inset(-70% -70% -70% -70%);transform:none}
.cta .pill{font-size:clamp(12px,1.05vw,15px);padding:clamp(15px,2.1vh,21px) clamp(42px,5.2vw,76px)}

/* ================= the foot: the bar motif ================= */
.horizon{position:absolute;left:0;right:0;bottom:0;height:var(--band-h);
  z-index:1;pointer-events:none;overflow:visible;
  translate:calc(var(--k-off-foot-x) * 1px) calc(var(--k-off-foot-y) * 1px)}
.horizon .wave{position:absolute;inset:0;width:100%;height:100%}
/* The long curve draws itself left to right rather than being there from
   the start. pathLength="1" on the path in the markup is what makes this
   possible without measuring: the dash array is in path units, so one unit
   is the whole line whatever the viewport does to it. */
.horizon .wl{stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset calc(1.9s * var(--k-anim)) calc(.2s * var(--k-anim)) var(--ease)}
.in .horizon .wl,.still .horizon .wl{stroke-dashoffset:0}
/* The box and the drawing have to agree. They did not: the viewBox was 420
   wide inside a box declared at 760/300, so the art was letterboxed and drew
   at about 14% of the screen. The viewBox is now trimmed to the ink and the
   box carries its ratio, so --band-h is the only thing that sets the size. */
.horizon .rig{position:absolute;left:50%;bottom:0;
  translate:calc(-50% + var(--k-rig-x) * 1%) 0;
  height:100%;width:auto;aspect-ratio:478/176;
  clip-path:inset(100% 0 0 0);
  transition:clip-path calc(1.25s * var(--k-anim)) calc(.45s * var(--k-anim)) var(--ease)}
.in .horizon .rig,.still .horizon .rig{clip-path:inset(0 0 0 0)}
/* the lit ground is the bars' own baseline: 26 of the rig's 176 units up
   from its foot */
/* the lit ground opens from the centre out, under the bars as they rise */
.horizon .glowline{transform:scaleX(0);
  transition:transform calc(1.4s * var(--k-anim)) calc(.5s * var(--k-anim)) var(--ease)}
.in .horizon .glowline,.still .horizon .glowline{transform:scaleX(1)}
.horizon .glowline{position:absolute;left:0;right:0;
  bottom:calc(.1477 * var(--band-h));height:1px;
  background:linear-gradient(90deg,transparent,rgba(225,168,78,.55) 22%,
    rgba(243,217,106,.85) 50%,rgba(225,168,78,.55) 78%,transparent);
  box-shadow:0 0 calc(30px * var(--k-glow)) rgba(225,168,78,.5)}

/* ================= the ABR channel =================
   Anchor: mock 03 Product / Moto Card, the one ABR named as a keeper.
   Two mechanisms and only two: a curved wall of cards standing in real
   depth around one central card, and a centred headline block of two
   lines, a subline and a pill. Not a card grid, which is the layout
   CLAUDE.md section 2 says to avoid unless the anchor uses it.

   The arc is generated rather than hand-placed: every card carries an
   index --i, and its angle and depth come from two --k- values, so the
   curve is one thing to tune in the lab instead of seven transforms to
   keep in step. */
.channel{position:relative;z-index:2;background:var(--k-black);
  padding:clamp(64px,11vh,132px) var(--gutter) clamp(56px,9vh,110px);
  border-top:1px solid rgba(225,168,78,.13)}

.ch-head{text-align:center;max-width:74ch;margin:0 auto}
.eyebrow{font-size:clamp(9.5px,.76vw,11.5px);font-weight:600;letter-spacing:.3em;
  text-transform:uppercase;color:var(--k-gold-deep)}
.ch-title{margin-top:clamp(10px,1.6vh,18px);overflow:clip;overflow-clip-margin:.14em}
.ch-title span{display:block;
  font-size:min(calc(var(--k-ch-title) * 1vw),calc(var(--k-ch-title-max) * 1rem));
  font-weight:800;font-variation-settings:'wdth' 104;letter-spacing:.01em;
  line-height:1;text-transform:uppercase;
  background-image:linear-gradient(177deg,#fbe9a6 2%,var(--k-gold-light) 24%,
    var(--k-gold) 56%,#c98f34 84%,var(--k-gold-deep));
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  transform:translateY(110%);
  transition:transform calc(.95s * var(--k-anim)) var(--ease)}
.seen .ch-title span{transform:none}

/* Every gap the team still owes is marked the same way and says so.
   A slot that looks like finished copy is worse than an empty one. */
.slot{position:relative;margin-top:clamp(22px,3vh,34px);
  font-size:clamp(12px,.92vw,14.5px);line-height:1.7;color:#9a9488;
  padding:10px 14px;border:1px dashed rgba(225,168,78,.38);border-radius:8px;
  display:inline-block;max-width:62ch}
.slot::before{content:attr(data-slot);position:absolute;top:-8px;left:12px;
  background:var(--k-black);padding:0 7px;
  font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--k-gold)}

/* ---- the wall ---- */
.wall{position:relative;margin:clamp(36px,6vh,74px) auto 0;
  width:100%;max-width:1180px;height:calc(var(--k-wall-h) * 1px);
  perspective:calc(var(--k-wall-p) * 1px);
  translate:calc(var(--k-off-wall-x) * 1px) calc(var(--k-off-wall-y) * 1px)}
/* The radius is what sets both the curve and the width of the arc, so it is
   capped against the viewport: a fixed pixel radius is wider than the screen
   on a laptop and the outer cards get cut off by the window. */
.wall{--r:min(calc(var(--k-wall-r) * 1px),72vw)}
.arc{position:absolute;inset:0;transform-style:preserve-3d;
  /* the whole cylinder is pushed back by its own radius, so the centre card
     lands at z 0 and the outer ones recede from there instead of the entire
     wall flying at the viewer */
  /* --wx and --wy are written by the script each frame: the cursor answer and
     the idle drift. Unset (still mode, or no script at all) they fall back to 0
     and the wall stands exactly where it did before. */
  transform:rotateX(calc((var(--k-wall-tilt) + var(--wy,0)) * 1deg))
            rotateY(calc(var(--wx,0) * 1deg))
            translateZ(calc(var(--r) * -1))}

/* ---- the cards ----
   03's card system is the anchor ABR named by name, and two things had drifted
   away from it.

   Its material was gone. 03's card had a gold edge, an inset highlight along
   the top, a reflection under it and a light sweeping across the face. This had
   a bone hairline at 11 percent over a grey gradient, which is the default dark
   card that every tool and every component library produces. Ghady called that
   generic on 2026-09-12 and he was right.

   And 03 had ONE card. It carried the channel's identity once, because one card
   standing alone is the channel. Repeating that avatar and that name across all
   seven turned a channel into seven identical social posts, which is the other
   half of why it read as stock.

   So the identity sits on the pinned card alone, because there the channel is
   speaking rather than posting, and the message cards are his posts as the
   captures in client-assets/README.md actually show them. Every card is tagged
   with the diamond from his own logo instead of an avatar, and with what kind of
   post it is, which is what keeps "each card reads plainly as a trade"
   (mocks/_core.md item 4) without the engagement numbers he asked to remove. */
.card{position:absolute;left:50%;top:50%;
  --cw:clamp(168px,14.2vw,calc(var(--k-card-w) * 1px));width:var(--cw);
  --ang:calc(var(--i) * var(--k-wall-spread) + var(--side,0) * var(--k-wall-pingap));
  background:linear-gradient(162deg,#121214,#08080a 64%);
  border:1px solid rgba(225,168,78,.26);border-radius:14px;
  padding:13px 15px 12px;overflow:hidden;
  /* The strip of an outer card that tucks under its inner neighbour is kept
     empty, so the wall can overlap like a fanned deck without covering text.
     Cards left of the pinned one tuck on their right, cards right of it on
     their left, and the pinned card tucks under nothing. */
  padding-left:calc(15px + max(0px, var(--side,0) * var(--k-wall-tuck) * var(--cw)));
  padding-right:calc(15px + max(0px, var(--side,0) * var(--k-wall-tuck) * var(--cw) * -1));

  box-shadow:0 34px 64px rgba(0,0,0,.66),inset 0 1px 0 rgba(255,255,255,.05);
  transform-style:preserve-3d;
  /* the arc: rotate out from the centre, then push back along the card's
     own Z so the far cards sit deeper as well as wider.

     The last rotation is what stops the fan bugging into itself. A card turned
     through its full arc angle pivots about its own centre, so its inner edge
     swings FORWARD of the plane while its outer edge swings back. Where two
     cards overlap it was therefore the outer card's forward edge meeting the
     inner card's receding one, the two were within a few pixels of each other
     in depth, and the browser fell back to document order: the left half of
     the wall stacked correctly by luck and the right half stacked backwards,
     with each far card painted over the near one and over its text. Measured
     with the cards flooded in flat colour, not by eye.

     Turning each card through nine tenths of its angle instead leaves the
     curve looking the same and moves the two edges far enough apart in depth
     for the sort to be decisive. Every pair now paints inner over outer at
     every width, which is the order the tuck below was always written for. */
  transform:translate(-50%,-50%)
            rotateY(calc(var(--ang) * 1deg))
            translateZ(var(--r))
            rotateY(calc(var(--ang) * (var(--k-wall-face) - 1) * 1deg))
            scale(.84);
  opacity:0;
  /* scale here is the independent property, not the one inside transform, so a
     hover cannot disturb the arc placement the transform is holding. */
  scale:1;
  transition:transform calc(1.1s * var(--k-anim)) var(--cd,0ms) var(--ease),
             opacity calc(.7s * var(--k-anim)) var(--cd,0ms),
             scale .34s var(--ease),border-color .34s,box-shadow .34s}
.seen .card{opacity:1;
  transform:translate(-50%,-50%)
            rotateY(calc(var(--ang) * 1deg))
            translateZ(var(--r))
            rotateY(calc(var(--ang) * (var(--k-wall-face) - 1) * 1deg))
            scale(1)}
.card:nth-child(1){--cd:60ms}   .card:nth-child(2){--cd:120ms}
.card:nth-child(3){--cd:180ms}  .card:nth-child(4){--cd:0ms}
.card:nth-child(5){--cd:180ms}  .card:nth-child(6){--cd:120ms}
.card:nth-child(7){--cd:60ms}

/* 03's sweep, restored. One pass across the face as the card lands, never a
   loop: a light that keeps crossing a card is a component-library tic, and one
   that crosses as the object arrives is the object catching the light. Killed
   with everything else by body.still. */
.card::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(115deg,transparent 32%,rgba(255,255,255,.10) 46%,
    rgba(255,255,255,.02) 53%,transparent 62%);
  transform:translateX(-125%)}
.seen .card::after{animation:cardsweep calc(1.5s * var(--k-anim)) var(--ease)
  calc(var(--cd,0ms) + .5s * var(--k-anim)) 1 forwards}
@keyframes cardsweep{to{transform:translateX(125%)}}

/* The spotlight. Straight out of Ghady's own 21st.dev saves, where Spotlight
   Card is the most-saved thing in the list by a distance (7.8k), sitting beside
   Image Mouse Trail, Text Cursor Proximity and Magnetic Dock. The pattern
   running through all of them is the same: the surface answers the cursor
   instead of waiting for it.

   A gold pool follows the pointer across the face. The card keeps its own
   colour; this only lifts the part being looked at, which is what stops a wall
   of seven reading as wallpaper.

   z-index is deliberate. The glow sits above the card's own background and
   below its text, so it lights the card rather than washing the type out:
   ::before at 0, the content at 1, and the arrival sweep at 2 over everything. */
.card::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  opacity:0;transition:opacity .34s var(--ease);
  background:radial-gradient(200px circle at var(--mx,50%) var(--my,50%),
    rgba(225,168,78,.17),rgba(225,168,78,.05) 38%,transparent 66%)}
.card > *{position:relative;z-index:1}
.card::after{z-index:2}
@media (hover:hover){
  .seen .card:hover::before{opacity:1}
}

/* The tick is the diamond from his logo, not an avatar. It says the post is
   his without spending a name and a face on every card. */
.card .kind{display:flex;align-items:center;justify-content:space-between;
  gap:10px;margin-bottom:10px;padding-bottom:9px;
  border-bottom:1px solid rgba(225,168,78,.15);
  font-size:8px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--k-gold)}
.card .kind::before{content:"";width:7px;height:7px;flex:none;
  background:var(--k-gold);transform:rotate(45deg)}

/* What he actually said, in the weight he said it. White is real here rather
   than bone, which is the third colour mocks/_core.md item 5 asks for. */
.card .say{font-size:clamp(12.5px,1.05vw,15px);font-weight:600;line-height:1.34;
  letter-spacing:.004em;color:#f7f5f0}
.card .say.sm{font-size:clamp(10.8px,.86vw,12.5px);font-weight:500;
  line-height:1.55;color:#c8c2b5}
/* "Close" is the entire post. Setting it small would be a lie about the
   channel: one word arrives and the trade is over. */
.card .say.solo{font-size:clamp(17px,1.75vw,25px);font-weight:700;
  letter-spacing:.03em;text-transform:uppercase;color:var(--k-gold-light);
  line-height:1.1;padding:6px 0 2px}

/* The reply stub. "Entry 4665 / Sl 4685" was a reply to "Sell gold nw" in the
   same minute (telegram-signal-01), and quoting the parent is the one detail
   here that no component library would ever hand you. */
.card .q{margin:0 0 10px;padding:5px 0 5px 9px;
  border-left:2px solid var(--k-gold);border-radius:0 3px 3px 0;
  background:linear-gradient(90deg,rgba(225,168,78,.08),transparent 72%);
  font-size:10.5px;line-height:1.45;color:#9a9488}

/* The levels, as a ticket reads: label small and quiet, number large and gold,
   figures lined up so two cards side by side can be compared. */
.card .lv{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:11px}
.card .lv > div{display:flex;flex-direction:column;gap:2px}
.card .lv dt{font-size:8px;letter-spacing:.2em;text-transform:uppercase;
  color:#7d786d}
.card .lv dd{margin:0;font-size:clamp(12px,1vw,14.5px);font-weight:600;
  font-variant-numeric:tabular-nums;color:var(--k-gold-light)}

.card .lots{margin:10px 0 0;display:grid;gap:5px}
.card .lots > div{display:flex;justify-content:space-between;gap:12px;
  font-variant-numeric:tabular-nums}
.card .lots dt{font-size:10px;color:#8f8a7e}
.card .lots dd{margin:0;font-size:10px;font-weight:600;color:var(--k-gold-light)}

.card .post{margin-top:11px;padding-top:8px;
  border-top:1px solid rgba(244,242,236,.07);
  font-size:8px;letter-spacing:.16em;text-transform:uppercase;color:#6f6a60}

/* a voice note is a real post type in his channel, so it reads as one */
.card .vn{display:flex;align-items:center;gap:10px;padding:4px 0 2px}
.card .vn .wave{flex:1;height:18px;
  background:repeating-linear-gradient(90deg,
    var(--k-gold-deep) 0 2px,transparent 2px 5px);
  -webkit-mask-image:linear-gradient(90deg,#000 62%,transparent);
  mask-image:linear-gradient(90deg,#000 62%,transparent);opacity:.75}
.card .vn b{font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;
  color:var(--k-gold-light)}

/* The pinned card is the object the wall stands around, so it comes forward,
   holds the gold edge, and is the only card that carries the channel plate:
   here the channel is speaking, not posting. His words, unchanged. */
.card.pin{width:clamp(206px,19.6vw,calc(var(--k-card-pin) * 1px));z-index:5;
  border-color:rgba(225,168,78,.45);
  box-shadow:0 36px 84px rgba(0,0,0,.74),inset 0 1px 0 rgba(255,255,255,.07),
             0 0 calc(64px * var(--k-glow)) -22px rgba(225,168,78,.5)}
.card.pin .plate{display:flex;align-items:center;gap:9px;margin-bottom:11px;
  padding-bottom:10px;border-bottom:1px solid rgba(225,168,78,.24)}
.card.pin .ava{width:24px;height:24px;border-radius:50%;flex:none;
  background:linear-gradient(150deg,var(--k-gold-light),#8a6224);color:#14120f;
  font-size:11px;font-weight:700;
  display:flex;align-items:center;justify-content:center}
.card.pin .who{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
  line-height:1.3;color:var(--k-bone)}
.card.pin .who small{display:block;margin-top:2px;font-size:8.5px;
  letter-spacing:.13em;text-transform:none;color:#8a8579}
.card.pin .disc{font-family:var(--sans);font-size:11.5px;line-height:1.62;
  letter-spacing:.005em;color:#b9b2a4}

.card.slotcard{border-style:dashed;border-color:rgba(225,168,78,.4)}

/* A wall of his posts is worth reading, so a card answers being pointed at.
   Only once the wall has arrived, and only where hover is real: on a phone a
   sticky :hover would leave one card lifted for good. */
@media (hover:hover){
  .seen .card:hover{scale:1.055;border-color:rgba(225,168,78,.5);
    box-shadow:0 36px 72px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.08),
               0 0 calc(44px * var(--k-glow)) -18px rgba(225,168,78,.45)}
  .seen .card.pin:hover{border-color:rgba(225,168,78,.66)}
}


/* ================= the card is switchable =================
   Three times now the note has been that the cards look generic, and three
   times I answered by changing something inside the same object: the contents,
   then the edge, then the light on it. The silhouette never moved, which is
   what was actually being judged.

   So the object itself is a switch. `data-card` on the body picks it, the lab
   can set it, and `?card=` puts it in a link. The wall, the arc, the reveal,
   the spotlight and the geometry are untouched by all of it: a treatment only
   ever changes surface and colour, never layout, so switching cannot break the
   composition that was already approved.

     panel  the dark rounded card that has been live (kept, to compare against)
     slip   a printed dealing ticket on warm stock
     plate  a machined plate, chamfered at the diamond's own angle

   slip is the default because it is the only one of the three that puts real
   white on the page. mocks/_core.md item 5 asks for "white, gold and black,
   with real white somewhere, not only black plus gold," and this section had
   none at all. It is also the closest to what Ghady actually saves: almost
   every card reference in his 52 bookmarks sits on light stock, not dark.
   ========================================================= */

/* ---------- slip: a printed dealing ticket ---------- */
[data-card="slip"] .card{
  background:linear-gradient(172deg,#f7f3ea,#e7e1d2);
  border:1px solid rgba(20,18,15,.16);border-left:4px solid var(--k-gold);
  border-radius:2px;
  box-shadow:0 26px 54px rgba(0,0,0,.68),0 2px 0 rgba(0,0,0,.4)}
[data-card="slip"] .card .kind{color:#8a6a24;
  border-bottom-color:rgba(20,18,15,.18)}
[data-card="slip"] .card .kind::before{background:#8a6a24}
[data-card="slip"] .card .say{color:#14120f}
[data-card="slip"] .card .say.sm{color:#3d382e}
[data-card="slip"] .card .say.solo{color:#14120f}
[data-card="slip"] .card .q{border-left-color:#8a6a24;color:#4a453a;
  background:linear-gradient(90deg,rgba(138,106,36,.12),transparent 72%)}
[data-card="slip"] .card .lv dt,
[data-card="slip"] .card .lots dt{color:#6b6558}
[data-card="slip"] .card .lv dd,
[data-card="slip"] .card .lots dd{color:#14120f}
[data-card="slip"] .card .post{color:#6b6558;
  border-top-color:rgba(20,18,15,.14)}
[data-card="slip"] .card .vn .wave{background:repeating-linear-gradient(90deg,
  #8a6a24 0 2px,transparent 2px 5px);opacity:.6}
[data-card="slip"] .card .vn b{color:#14120f}
/* the pinned slip is the one that stays dark, so the channel's own voice still
   leads the wall instead of disappearing into a row of identical paper */
[data-card="slip"] .card.pin{
  background:linear-gradient(162deg,#141416,#08080a 64%);
  border:1px solid rgba(225,168,78,.5);border-left:4px solid var(--k-gold);
  box-shadow:0 36px 84px rgba(0,0,0,.76),
             0 0 calc(64px * var(--k-glow)) -22px rgba(225,168,78,.55)}
[data-card="slip"] .card.pin .plate{border-bottom-color:rgba(225,168,78,.26)}
[data-card="slip"] .card.pin .who{color:var(--k-bone)}
[data-card="slip"] .card.pin .who small{color:#8a8579}
[data-card="slip"] .card.pin .disc{color:#b9b2a4}
[data-card="slip"] .card.pin .post{color:#6f6a60;
  border-top-color:rgba(244,242,236,.07)}
[data-card="slip"] .card.slotcard{border-style:dashed;
  border-color:rgba(20,18,15,.3);border-left:4px dashed var(--k-gold)}
/* a white sweep is invisible on paper, and a gold spotlight on paper reads as
   a stain, so both invert: the light that crosses a slip is a shadow */
[data-card="slip"] .card::after{background:linear-gradient(115deg,
  transparent 32%,rgba(20,18,15,.10) 46%,rgba(20,18,15,.03) 53%,transparent 62%)}
[data-card="slip"] .card::before{background:radial-gradient(200px circle at
  var(--mx,50%) var(--my,50%),rgba(138,106,36,.16),rgba(138,106,36,.05) 38%,
  transparent 66%)}
[data-card="slip"] .card.pin::after{background:linear-gradient(115deg,
  transparent 32%,rgba(255,255,255,.10) 46%,rgba(255,255,255,.02) 53%,transparent 62%)}
[data-card="slip"] .card.pin::before{background:radial-gradient(200px circle at
  var(--mx,50%) var(--my,50%),rgba(225,168,78,.17),rgba(225,168,78,.05) 38%,
  transparent 66%)}
@media (hover:hover){
  [data-card="slip"] .seen .card:hover{border-color:rgba(20,18,15,.3);
    border-left-color:var(--k-gold-light);
    box-shadow:0 34px 64px rgba(0,0,0,.72),0 2px 0 rgba(0,0,0,.45)}
}

/* ---------- plate: a machined object ---------- */
[data-card="plate"] .card{
  background:var(--plate-face);
  border:0;border-radius:0;
  /* one corner cut at the diamond's own angle, from the shared --plate- values */
  clip-path:var(--plate-clip);
  box-shadow:var(--plate-shadow)}
/* the lit edge, top and left only, because the light is up and left */
[data-card="plate"] .card::before{
  background:
    radial-gradient(200px circle at var(--mx,50%) var(--my,50%),
      rgba(225,168,78,calc(.17 * var(--spot))),rgba(225,168,78,calc(.05 * var(--spot))) 38%,transparent 66%),
    var(--plate-edge);
  opacity:1}
/* The lit edges and the spotlight share this one layer, and the edges are
   always on, so the layer cannot fade in on hover the way it does for panel
   and slip. Left as it was, every plate carried a permanent gold smudge in its
   centre whether or not anything was pointing at it. So the spotlight's own
   alpha is scaled by --spot instead: 0 at rest, 1 under the cursor, and
   registered with @property so the change transitions rather than snaps. */
@property --spot{syntax:'<number>';inherits:true;initial-value:0}
[data-card="plate"] .card{
  transition:transform calc(1.1s * var(--k-anim)) var(--cd,0ms) var(--ease),
             opacity calc(.7s * var(--k-anim)) var(--cd,0ms),
             scale .34s var(--ease),box-shadow .34s,--spot .34s var(--ease)}
@media (hover:hover){
  [data-card="plate"] .seen .card:hover{--spot:1;box-shadow:0 34px 66px rgba(0,0,0,.76)}
}
/* The corner cut needs 24px clear on the right, except on cards left of the
   pinned one. Those tuck on their right, so the tuck already clears the cut,
   and a second 24px pushed their labels onto two lines at laptop widths. */
[data-card="plate"] .card .kind{margin-right:calc(24px * (1 + min(0, var(--side,0))))}
[data-card="plate"] .card.pin{
  background:
    linear-gradient(100deg,rgba(255,255,255,.07),transparent 38%),
    repeating-linear-gradient(92deg,#15151a 0 2px,#101014 2px 4px);
  border:0;
  box-shadow:0 36px 84px rgba(0,0,0,.78),
             0 0 calc(64px * var(--k-glow)) -22px rgba(225,168,78,.5)}
[data-card="plate"] .card.pin .plate{margin-right:24px}
[data-card="plate"] .card.slotcard{
  background:repeating-linear-gradient(92deg,#0d0d10 0 2px,#0a0a0c 2px 4px)}
[data-card="plate"] .card.slotcard::before{
  background:
    radial-gradient(200px circle at var(--mx,50%) var(--my,50%),
      rgba(225,168,78,calc(.14 * var(--spot))),transparent 66%),
    linear-gradient(180deg,rgba(243,217,106,.3),transparent 2px),
    linear-gradient(90deg,rgba(225,168,78,.22),transparent 2px)}

/* Below 1100px the arc is a flat column and the cards are full width, where a
   20px chamfer on a 420px card is a nick rather than a cut. Scale it up so the
   object still reads as machined at phone size. */
@media (max-width:1100px){
  /* the shared cut, so the Academy's cards get the same 34px when they stack */
  :root{--plate-cut:34px}
  [data-card="plate"] .card,
  [data-card="plate"] .card::before{clip-path:var(--plate-clip)}
}
/* ---- the facts, the action, the gaps ---- */
.ch-facts{list-style:none;display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(18px,3vw,54px);margin:clamp(40px,6.5vh,80px) auto 0;
  max-width:1040px;text-align:center}
.ch-facts li{display:flex;flex-direction:column;gap:5px;min-width:88px}
.ch-facts b{font-size:clamp(16px,1.55vw,23px);font-weight:800;letter-spacing:.01em;
  color:var(--k-gold-light)}
.ch-facts span{font-size:clamp(9.5px,.74vw,11.5px);letter-spacing:.17em;
  text-transform:uppercase;color:#8f8a7e}

.ch-act{text-align:center;margin-top:clamp(30px,5vh,58px)}
.ch-note{margin-top:14px;font-size:clamp(10px,.76vw,12px);letter-spacing:.03em;
  color:#807a6f}

.pending{display:flex;flex-wrap:wrap;gap:clamp(14px,2vw,26px);
  max-width:1040px;margin:clamp(40px,6vh,76px) auto 0}
.pend{flex:1 1 320px;position:relative;padding:20px 20px 18px;
  border:1px dashed rgba(225,168,78,.3);border-radius:10px}
.pend::before{content:attr(data-slot);position:absolute;top:-8px;left:14px;
  background:var(--k-black);padding:0 7px;font-size:8.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--k-gold)}
.pend h3{font-size:clamp(12.5px,1vw,15px);font-weight:600;letter-spacing:.04em;
  color:var(--k-bone)}
.pend p{margin-top:8px;font-size:clamp(10.5px,.8vw,12.5px);line-height:1.7;color:#87816f}

/* the block below the wall arrives as one, after it */
/* The clip has to bleed past the top and sides at the end of the reveal, or
   it crops the things that sit outside the box: the slot labels are notched
   into the border at top:-8px and were being cut in half by their own
   reveal. Only the bottom edge does the wiping. */
.ch-facts,.ch-act,.pending,.slot-line{
  clip-path:inset(0 -10% 100% -10%);transform:translateY(14px);
  transition:clip-path calc(.85s * var(--k-anim)) var(--rd,0ms) var(--ease),
             transform calc(.85s * var(--k-anim)) var(--rd,0ms) var(--ease)}
.slot-line{--rd:120ms}
.ch-facts{--rd:240ms} .ch-act{--rd:330ms} .pending{--rd:330ms}
.seen .ch-facts,.seen .ch-act,.seen .pending,.seen .slot-line{
  clip-path:inset(-30% -10% -40% -10%);transform:none}

/* Below this the arc stops being a wall and becomes a pile, so the cards come
   out of 3D and stack. The number is not a guess: the cards have a 160px floor
   so they stay readable, and the arc only has room for seven of those once the
   viewport is about 1100px. Narrower than that they overlap and cover each
   other's text. The mechanism is kept where it reads and dropped where it does
   not, rather than squeezed until it breaks. */
@media (max-width:1100px){
  .wall{height:auto;perspective:none;max-width:560px}
  .arc{position:static;transform:none;display:flex;flex-direction:column;
    align-items:center;gap:14px}
  .card,.seen .card{position:static;width:100%;max-width:420px;transform:none}
  .card{padding-left:15px;padding-right:15px}
  .card{transform:translateY(16px)}
  .seen .card{transform:none}
  .card.pin{width:100%;max-width:420px;order:-1}
}
@media (max-width:520px){
  .ch-facts{gap:16px 22px}
  .ch-facts li{min-width:74px}
  .pend{flex:1 1 100%}
}

/* ================= the academy =================
   Built from docs/academy-brief.md, on two references and only what was
   taken from each: mock 03's Academy gives the two credits columns in the
   side gutters, and Ghady's own black-and-gold image gives the centred
   stack (the mark, the name under it, two cards) on black.

   The name reads the landing's own gold type and travelling light from the
   same --type- values, so the two gold names on the page are one system.
   The cards are plate, the material picked for the channel, read from the
   same --plate- values, so the two card sections cannot drift apart. */
.academy{position:relative;z-index:2;background:var(--k-black);
  overflow:hidden;overflow:clip;text-align:center;
  padding:clamp(72px,12vh,140px) var(--gutter) clamp(64px,10vh,120px);
  border-top:1px solid rgba(225,168,78,.13)}

/* ---- the credits ----
   Mock 03's mechanism: the nine beginner topics in two columns at the edges,
   one running up and one running down, like film credits. On black rather
   than 03's light band, because the site is black and Ghady dropped the white
   section from his landing reference.

   The loop is one translateY(-50%) over a list built as exactly two identical
   halves. Each item carries its own bottom padding instead of the list using
   gap, because a flex gap leaves the two halves one gap apart and the loop
   would jump by half a gap at the seam on every pass. */
.credits{position:absolute;inset:0;z-index:0;pointer-events:none;
  translate:calc(var(--k-off-credits-x) * 1px) calc(var(--k-off-credits-y) * 1px);
  clip-path:inset(0 0 100% 0);
  transition:clip-path calc(1.6s * var(--k-anim)) calc(.1s * var(--k-anim)) var(--ease)}
.seen .credits{clip-path:inset(0 0 0 0)}
.roll-col{position:absolute;top:0;bottom:0;width:min(18vw,300px);overflow:hidden;
  opacity:var(--k-credits-op);
  /* faded out at the top, the bottom and toward the centre, so the columns
     stand behind the cards instead of competing with them */
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),
                     linear-gradient(90deg,#000 22%,transparent 78%);
          mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),
                     linear-gradient(90deg,#000 22%,transparent 78%);
  -webkit-mask-composite:source-in;mask-composite:intersect}
.roll-col.l{left:0}
.roll-col.r{right:0;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),
                     linear-gradient(270deg,#000 22%,transparent 78%);
          mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),
                     linear-gradient(270deg,#000 22%,transparent 78%)}
.roll{list-style:none;margin:0;text-align:left;
  padding:0 0 0 clamp(16px,2.8vw,48px);
  animation:credits calc(var(--k-credits) * 1s) linear infinite}
/* the right column runs the other way and a little slower, so the two never
   line up into one moving grid */
.roll-col.r .roll{text-align:right;padding:0 clamp(16px,2.8vw,48px) 0 0;
  /* A long topic has to overflow toward the centre, where the mask dissolves
     it. Left to text-align, nowrap text wider than the column overflowed to the
     right instead and was cut off hard at the edge of the screen. Flex-end puts
     each item's end on the column's end and lets it run out leftward. */
  display:flex;flex-direction:column;align-items:flex-end;
  animation-direction:reverse;animation-duration:calc(var(--k-credits) * 1.13s)}
@keyframes credits{from{transform:translateY(0)}to{transform:translateY(-50%)}}
.roll li{display:block;padding-bottom:clamp(20px,3vh,34px);white-space:nowrap}
.roll b{display:block;font-size:calc(var(--k-credits-fs) * .34px);font-weight:600;
  letter-spacing:.24em;color:var(--k-gold);font-variant-numeric:tabular-nums}
.roll span{display:block;margin-top:2px;
  font-size:calc(var(--k-credits-fs) * 1px);font-weight:700;line-height:1.08;
  font-variation-settings:'wdth' 96;letter-spacing:-.004em;color:#8c8677}
.roll small{display:block;margin-top:5px;font-size:9px;letter-spacing:.26em;
  text-transform:uppercase;color:var(--k-gold-deep)}
.roll .tbc small{color:#d99a3a}

/* ---- the stack ---- */
.ac-stage{position:relative;z-index:1;max-width:1200px;margin:0 auto}
.ac-core{display:flex;flex-direction:column;align-items:center}

/* the mark: smaller than the landing's, so the hero stays the hero */
.ac-mark{width:min(calc(var(--k-ac-mark) * 1vw),calc(var(--k-ac-mark-max) * 1px));
  aspect-ratio:1;position:relative;flex:none;overflow:hidden;
  translate:calc(var(--k-off-acmark-x) * 1px) calc(var(--k-off-acmark-y) * 1px)}
.ac-mark canvas{width:100%;height:100%}
.no-gl .ac-mark canvas{display:none}

/* ABR ACADEMY, on the landing name's own type dials and its own light.
   Revealed by a mask and a rise, never by opacity. */
.ac-title{margin-top:clamp(4px,1vh,12px);padding-bottom:.08em;
  overflow:hidden;overflow:clip;overflow-clip-margin:.16em;
  translate:calc(var(--k-off-actitle-x) * 1px) calc(var(--k-off-actitle-y) * 1px)}
.ac-title span{display:block;
  font-size:min(calc(var(--k-ac-title) * 1vw),calc(var(--k-ac-title-max) * 1rem));
  font-weight:var(--k-name-wght);font-variation-settings:'wdth' var(--k-name-wdth);
  letter-spacing:calc(var(--k-name-track) * 1em);
  line-height:1;text-transform:uppercase;white-space:nowrap;
  background-image:var(--type-sweep),var(--type-gold);
  background-size:280% 100%,100% 100%;background-repeat:no-repeat,no-repeat;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  text-shadow:0 0 calc(30px * var(--k-glow)) rgba(203,148,58,.30);
  animation:sheen calc(var(--k-sheen) * 1s) linear infinite;
  transform:translateY(110%);
  transition:transform calc(1.05s * var(--k-anim)) calc(.2s * var(--k-anim)) var(--ease)}
.seen .ac-title span{transform:none}
body.still .ac-title span{background-position:56% 0,0 0}

/* ---- the two levels, as a pricing section ----
   Ghady, 2026-09-13: "I dont like the cards design. I want it basically like a
   pricing section from 21st.dev." None of his 58 saves is one, so this is built on
   the anatomy the genre shares, closest to LN's Two-Plan Pricing Cards: two plans
   side by side, one highlighted by a pill on its top edge; each with a name and a
   line, a big figure with a small unit, a hairline, a list with checks, and a
   full-width button.

   Two things are ABR's rules rather than the genre's. The figure is never a price,
   because the academy's pricing is not public: it is the length of the level, or
   "Custom", with "Pricing through customer service" under it. And the pill is a
   fact from his call notes, not "Most popular", which would be a claim.

   The rows of the two cards are one subgrid, so every row (name, figure, list,
   button) lines up across both cards, and the two are the same height. What the
   button opens is a window over the page, not a panel inside the card (the level
   windows, further down), so nothing it does can change a card's height. */
.ac-cards{display:grid;justify-content:center;
  grid-template-columns:repeat(2,minmax(0,calc(var(--k-lvl-w) * 1px)));
  gap:clamp(16px,2.2vw,34px);margin-top:clamp(44px,6.5vh,76px)}
/* The entrance lives on the slot and the card's look lives on the card, so the two
   never compete for one property. The slot wipes and rises; nothing fades. */
.lvl-slot{position:relative;min-width:0;
  display:grid;grid-row:span 4;grid-template-rows:subgrid;row-gap:0;
  translate:calc(var(--k-off-accards-x) * 1px) calc(var(--k-off-accards-y) * 1px);
  clip-path:inset(0 -14% 100% -14%);transform:translateY(34px);
  transition:clip-path calc(1s * var(--k-anim)) var(--ld,0ms) var(--ease),
             transform calc(1.1s * var(--k-anim)) var(--ld,0ms) var(--ease)}
.lvl-slot:nth-child(1){--ld:calc(.2s * var(--k-anim))}
.lvl-slot:nth-child(2){--ld:calc(.32s * var(--k-anim))}
/* Each card is watched by its own observer rather than the section's, so a
   card below the fold (any phone, a short laptop) arrives when it is reached
   instead of having finished while the title was still on screen. */
.lvl-slot.seen{clip-path:inset(-20% -20% -30% -20%);transform:none}

.lvl{position:relative;text-align:left;min-width:0;
  display:grid;grid-row:span 4;grid-template-rows:subgrid;row-gap:0;
  background:linear-gradient(180deg,#111113,#09090a);
  border:1px solid rgba(244,242,236,.1);border-radius:18px;
  padding:clamp(24px,2.3vw,34px);
  box-shadow:0 34px 80px -34px rgba(0,0,0,.9);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease),border-color .3s}
/* the highlighted plan: a gold edge, the light pooled at its top, and the pill */
.lvl.hi{border-color:rgba(225,168,78,.55);
  background:radial-gradient(120% 52% at 50% 0%,rgba(225,168,78,.13),transparent 64%),
    linear-gradient(180deg,#131210,#0a0a09);
  box-shadow:0 0 0 1px rgba(225,168,78,.1),0 40px 96px -40px rgba(225,168,78,.36)}
/* Under the pointer a card rises a little. Ghady, 2026-09-13, who in the same
   note had the gold spotlight that followed the pointer taken off these cards.
   The hover sits on the slot, which never moves, and the card inside it is what
   lifts: hovered directly, a rising card would pull its bottom edge out from
   under a pointer resting there, lose the hover, drop back, and shake. */
@media (hover:hover){
  .lvl-slot.seen:hover .lvl{transform:translateY(calc(var(--k-lvl-lift) * -1px));
    box-shadow:0 48px 92px -36px rgba(0,0,0,.95)}
  .lvl-slot.seen:hover .lvl.hi{
    box-shadow:0 0 0 1px rgba(225,168,78,.16),0 54px 112px -40px rgba(225,168,78,.44)}
  .lvl-slot.seen:hover .lvl:not(.hi){border-color:rgba(225,168,78,.32)}
}
.lvl-pill{position:absolute;top:0;left:50%;translate:-50% -50%;z-index:2;
  padding:6px 13px;border-radius:999px;white-space:nowrap;
  background:var(--k-gold);color:#141008;
  font-size:9px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  box-shadow:0 8px 22px -8px rgba(225,168,78,.75)}

.lvl-head{padding-bottom:clamp(18px,1.8vw,24px)}
.lvl-name{font-size:clamp(20px,1.75vw,26px);font-weight:800;letter-spacing:.02em;
  line-height:1.1;color:var(--k-bone)}
.lvl-sub{margin-top:8px;font-size:clamp(9.5px,.74vw,11px);letter-spacing:.2em;
  text-transform:uppercase;color:var(--k-gold-deep)}
.lvl-price{padding:clamp(18px,1.8vw,24px) 0;
  border-top:1px solid rgba(244,242,236,.08);border-bottom:1px solid rgba(244,242,236,.08)}
/* the figure reads the same gold as the names on the page */
.lvl-fig{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 10px;line-height:1}
.lvl-fig b{font-size:clamp(44px,4.4vw,64px);font-weight:800;letter-spacing:-.01em;
  font-variation-settings:'wdth' var(--k-name-wdth);padding-bottom:.04em;
  background-image:var(--type-gold);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent}
.lvl-fig span{font-size:clamp(13px,1vw,15px);color:#9a9488}
.lvl-note{margin-top:10px;font-size:clamp(11px,.84vw,12.5px);color:#8f8a7e}
.lvl-feat{list-style:none;margin:0;padding:clamp(18px,1.8vw,24px) 0 clamp(20px,2vw,26px);
  display:grid;gap:12px;align-content:start}
.lvl-feat li{position:relative;padding-left:30px;
  font-size:clamp(13px,1.02vw,14.5px);line-height:1.5;color:#e9e5dc}
.lvl-feat li::before{content:"";position:absolute;left:0;top:.15em;
  width:18px;height:18px;border-radius:50%;box-sizing:border-box;
  border:1px solid rgba(225,168,78,.45);
  background:rgba(225,168,78,.12) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.6 6.3 5 8.6l4.5-5' fill='none' stroke='%23f3d96a' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/11px no-repeat}

/* the button: outlined, or filled gold on the highlighted plan, with a chevron
   pointing at the window it opens */
.lvl-btn{display:flex;align-items:center;justify-content:center;gap:12px;width:100%;
  font-family:inherit;font-size:clamp(10px,.76vw,11.5px);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--k-bone);background:transparent;
  border:1px solid rgba(244,242,236,.24);border-radius:12px;
  padding:14px 18px;cursor:pointer;
  transition:background .25s,color .25s,border-color .25s}
.lvl-btn::after{content:"";width:6px;height:6px;flex:none;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(-45deg);transition:transform .3s var(--ease)}
.lvl-btn:hover::after{transform:translateX(3px) rotate(-45deg)}
.lvl-btn:hover{border-color:var(--k-gold-light);color:var(--k-gold-light)}
.lvl.hi .lvl-btn{background:var(--k-gold);border-color:var(--k-gold);color:#141008}
.lvl.hi .lvl-btn:hover{background:var(--k-gold-light);border-color:var(--k-gold-light);color:#141008}
.lvl-btn:focus-visible{outline:2px solid var(--k-gold-light);outline-offset:3px}

/* ---- the card's contents arrive in order ----
   Ghady, 2026-09-13, picked from three: the badge drops onto the card's edge,
   the figure rises, the ticks come in row by row, and the button comes last.
   Every step counts from the card's own delay (--ld) on the page's two dials,
   --k-anim for every duration and delay and --k-stagger for the gap between
   the rows, so the lab's Speed, Stagger and Replay reach all of it. Clips and
   transforms only: all of it is type, and type never fades in. Still mode and
   reduced motion land it finished. Every start clip is empty rather than flush with
   the edge of its element: flush, the bleed band kept a 1px gold line on the card (the
   glow under the badge, the bottom row of the button) before either had arrived.
   All of it is scoped to .lvl-slot: the level windows reuse these classes, and
   nothing in a window may start hidden. */
.lvl{--seq-pill:.3s;--seq-fig:.42s;--seq-rows:.62s;--rows:4}

/* the badge drops from just above its place and settles */
.lvl-slot .lvl-pill{transform:translateY(-18px);clip-path:inset(-24px -24px calc(100% + 24px) -24px);
  transition:transform calc(.75s * var(--k-anim)) calc(var(--ld,0s) + var(--seq-pill) * var(--k-anim)) cubic-bezier(.34,1.45,.64,1),
             clip-path calc(.5s * var(--k-anim)) calc(var(--ld,0s) + var(--seq-pill) * var(--k-anim)) var(--ease)}
.lvl-slot.seen .lvl-pill{transform:none;clip-path:inset(-24px -24px -24px -24px)}

/* the figure rises past a fixed edge at the foot of its own row, the unit a
   beat behind the number */
.lvl-slot .lvl-fig{clip-path:inset(-20px -20px -4px -20px)}
.lvl-slot .lvl-fig b,.lvl-slot .lvl-fig span{transform:translateY(calc(100% + 16px));
  transition:transform calc(.9s * var(--k-anim)) calc(var(--ld,0s) + var(--seq-fig) * var(--k-anim)) var(--ease)}
.lvl-slot .lvl-fig span{transition-delay:calc(var(--ld,0s) + (var(--seq-fig) + .1s) * var(--k-anim))}
.lvl-slot.seen .lvl-fig b,.lvl-slot.seen .lvl-fig span{transform:none}

/* each row: the tick pops, and the line writes out from it */
.lvl-slot .lvl-feat li{--row-d:calc(var(--ld,0s) + (var(--seq-rows) + var(--ri,0) * var(--k-stagger) * 2ms) * var(--k-anim));
  clip-path:inset(-6px calc(100% + 8px) -6px -8px);
  transition:clip-path calc(.6s * var(--k-anim)) var(--row-d) var(--ease)}
.lvl-slot .lvl-feat li::before{transform:scale(.2);
  transition:transform calc(.5s * var(--k-anim)) var(--row-d) cubic-bezier(.34,1.56,.64,1)}
.lvl-feat li:nth-child(2){--ri:1}
.lvl-feat li:nth-child(3){--ri:2}
.lvl-feat li:nth-child(4){--ri:3}
.lvl-feat li:nth-child(5){--ri:4}
.lvl-feat li:nth-child(6){--ri:5}
.lvl-slot.seen .lvl-feat li{clip-path:inset(-6px -8px -6px -8px)}
.lvl-slot.seen .lvl-feat li::before{transform:none}

/* the button last, rising into place; its hover colours from above ride along
   with no delay */
.lvl-slot .lvl-btn{--btn-d:calc(var(--ld,0s) + (var(--seq-rows) + var(--rows) * var(--k-stagger) * 2ms + .04s) * var(--k-anim));
  clip-path:inset(calc(100% + 12px) -12px -12px -12px);transform:translateY(12px);
  transition:background .25s,color .25s,border-color .25s,
             clip-path calc(.6s * var(--k-anim)) var(--btn-d) var(--ease),
             transform calc(.7s * var(--k-anim)) var(--btn-d) var(--ease)}
.lvl-slot.seen .lvl-btn{clip-path:inset(-12px -12px -12px -12px);transform:none}

.topics{list-style:none;margin:0;padding:0}
.topics li{display:grid;grid-template-columns:32px 1fr auto;align-items:baseline;
  gap:10px;padding:9px 0;border-bottom:1px solid rgba(244,242,236,.07);
  font-size:clamp(12.5px,1vw,14.5px);line-height:1.45;color:#e9e5dc}
.topics li:last-child{border-bottom:0}
.topics b{font-size:10px;font-weight:600;letter-spacing:.14em;color:var(--k-gold);
  font-variant-numeric:tabular-nums}
.topics small{font-size:8px;letter-spacing:.18em;text-transform:uppercase;color:#d99a3a;
  border:1px dashed rgba(225,168,78,.5);border-radius:999px;padding:3px 8px;
  white-space:nowrap}
.lvl-facts{margin:0}
.lvl-facts > div{display:grid;grid-template-columns:minmax(84px,32%) 1fr;gap:12px;
  padding:9px 0;border-bottom:1px solid rgba(244,242,236,.07)}
.lvl-facts > div:last-child{border-bottom:0}
.lvl-facts dt{font-size:9px;letter-spacing:.18em;text-transform:uppercase;color:#8a8579;
  padding-top:3px}
.lvl-facts dd{margin:0;font-size:clamp(12.5px,1vw,14.5px);line-height:1.5;color:#e9e5dc}
.lvl-p{font-size:clamp(12.5px,1vw,14.5px);line-height:1.6;color:#e9e5dc}
.lvl-note{margin-top:8px;font-size:clamp(11px,.84vw,12.5px);line-height:1.6;color:#8f8a7e}
.lvl-win .slot{display:block;margin-top:22px;font-size:clamp(11px,.84vw,12.5px)}
/* the notch in a slot's border has to be the window's colour, not the page's */
.lvl-win .slot::before{background:#0e0e10}

/* ---- the level windows ----
   Ghady, 2026-09-13: "I don't like the dropdown method I want them to pop on the
   screen, like a mini window with all info". Each card's button opens a native
   dialog holding everything on file for its level, and nothing that is not. The
   dialog is only the frame and carries no padding, so a click on the dialog
   itself can only be a click on its backdrop. The body inside it scrolls when a
   screen is shorter than the window. The reset at the top of the file zeroes every
   margin, and a dialog centres itself by margin:auto, so the frame puts it back.
   The section centres its text; a window reads left, like the cards. */
.lvl-win{margin:auto;inset:0;padding:0;border:0;background:transparent;color:var(--k-bone);overflow:visible;
  text-align:left;
  width:min(calc(var(--k-win-w) * 1px),calc(100% - 32px));max-width:none;max-height:none}
.lvl-win::backdrop{background:rgba(4,4,5,.74);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.win-body{max-height:calc(100vh - 48px);max-height:calc(100dvh - 48px);
  overflow:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(225,168,78,.4) transparent;
  background:linear-gradient(180deg,#121214,#09090a);
  border:1px solid rgba(244,242,236,.12);border-radius:20px;
  padding:clamp(26px,3vw,42px);
  box-shadow:0 40px 110px -30px rgba(0,0,0,.95)}
.lvl-win.hi .win-body{border-color:rgba(225,168,78,.5);
  background:radial-gradient(120% 40% at 50% 0%,rgba(225,168,78,.12),transparent 64%),
    linear-gradient(180deg,#131210,#0a0a09);
  box-shadow:0 0 0 1px rgba(225,168,78,.08),0 40px 110px -30px rgba(0,0,0,.95)}
/* the close button belongs to the frame, not the body, so it stays in the
   corner while a phone scrolls the body under it */
.win-x{position:absolute;top:14px;right:14px;z-index:3;width:40px;height:40px;padding:0;
  border-radius:50%;border:1px solid rgba(244,242,236,.18);background:rgba(10,10,11,.72);
  color:var(--k-bone);cursor:pointer;
  transition:border-color .25s,color .25s,transform .3s var(--ease)}
.win-x::before,.win-x::after{content:"";position:absolute;left:50%;top:50%;
  width:14px;height:1.5px;background:currentColor;
  transform:translate(-50%,-50%) rotate(45deg)}
.win-x::after{transform:translate(-50%,-50%) rotate(-45deg)}
.win-x:hover{border-color:var(--k-gold-light);color:var(--k-gold-light);transform:rotate(90deg)}
.win-x:focus-visible{outline:2px solid var(--k-gold-light);outline-offset:3px}

.win-head{padding:0 52px clamp(16px,1.8vw,22px) 0;border-bottom:1px solid rgba(244,242,236,.08)}
.win-head .lvl-name{font-size:clamp(24px,2.1vw,30px)}
.win-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  gap:clamp(24px,3.4vw,52px);padding-top:clamp(18px,2vw,26px)}
.win-h{margin:0 0 10px;font-size:9.5px;font-weight:700;letter-spacing:.22em;
  text-transform:uppercase;color:var(--k-gold-deep)}
.win-col > * + .win-h{margin-top:26px}
.win-col .lvl-price{border-top:0;padding-top:0}
.win-col .lvl-feat{padding:4px 0 0}
@media (max-width:720px){
  .win-grid{grid-template-columns:minmax(0,1fr)}
}

/* The page behind a window stays where it was. Locking it takes the scrollbar
   away, so the page would widen under the backdrop and jump back on close, and
   scrollbar-gutter did not hold the width here. The script measures the scrollbar
   before it goes and hands its width back: as padding to the page, and to the two
   fixed layers, which size themselves to the viewport. */
html.win-open{overflow:hidden;padding-right:var(--win-sbw,0px)}
html.win-open .nav{right:var(--win-sbw,0px)}
/* the painter sets the canvas width inline, so max-width is what holds it */
html.win-open #bg{max-width:calc(100% - var(--win-sbw,0px))}

/* It pops: the frame springs up from a little smaller and lower while the
   backdrop darkens, then the rows inside write in one after another. Transforms
   and clips; the backdrop is the one thing that fades, and it holds no type.
   Closing is shorter and runs the other way. Still mode and reduced motion open
   and close it at once. */
@keyframes win-pop{from{transform:translateY(22px) scale(.92)}}
@keyframes win-shut{to{transform:translateY(12px) scale(.95)}}
@keyframes win-veil{from{opacity:0}}
@keyframes win-unveil{to{opacity:0}}
@keyframes win-row{from{clip-path:inset(-6px calc(100% + 8px) -6px -8px)}
  to{clip-path:inset(-6px -8px -6px -8px)}}
.topics li:nth-child(2){--ri:1}
.topics li:nth-child(3){--ri:2}
.topics li:nth-child(4){--ri:3}
.topics li:nth-child(5){--ri:4}
.topics li:nth-child(6){--ri:5}
.topics li:nth-child(7){--ri:6}
.topics li:nth-child(8){--ri:7}
.topics li:nth-child(9){--ri:8}
.lvl-win[open]{animation:win-pop calc(.5s * var(--k-anim)) cubic-bezier(.2,1.3,.35,1) backwards}
.lvl-win[open]::backdrop{animation:win-veil calc(.32s * var(--k-anim)) var(--ease) backwards}
.lvl-win[open] .lvl-feat li{animation:win-row calc(.5s * var(--k-anim))
  calc((.14s + var(--ri,0) * var(--k-stagger) * .8ms) * var(--k-anim)) var(--ease) backwards}
.lvl-win[open] .topics li{animation:win-row calc(.5s * var(--k-anim))
  calc((.2s + var(--ri,0) * var(--k-stagger) * .6ms) * var(--k-anim)) var(--ease) backwards}
.lvl-win[open] .lvl-facts > div{animation:win-row calc(.5s * var(--k-anim))
  calc(.3s * var(--k-anim)) var(--ease) backwards}
.lvl-win.closing{animation:win-shut calc(.2s * var(--k-anim)) var(--ease) forwards}
.lvl-win.closing::backdrop{animation:win-unveil calc(.2s * var(--k-anim)) var(--ease) forwards}

/* With no script, or no dialog support, the windows are not windows: they stand
   in the page under the cards, so everything they hold can still be read. */
.academy:not(.ac-js) .lvl-win{display:block;position:relative;inset:auto;z-index:1;
  width:auto;max-width:calc(var(--k-win-w) * 1px);margin:clamp(44px,6vh,70px) auto 0}
.academy:not(.ac-js) .win-body{max-height:none;overflow:visible}
.academy:not(.ac-js) .win-x{display:none}

.ac-pending{position:relative;z-index:1;text-align:left;
  /* As wide as the two cards above it. Wider, its edges sat out in the credits
     gutters, did not line up with anything, and let stray credit letters peek
     past its border. */
  max-width:calc(2 * var(--k-lvl-w) * 1px + clamp(16px,2.2vw,34px))}
/* a ground of their own: without one, the credits running behind showed
   straight through both boxes at laptop widths */
.ac-pending .pend{background:var(--k-black)}

/* ---- the cards either side of the logo ----
   The other reading of the brief, built so it can be judged by looking:
   Beginner left, the mark and the name between them, Advanced right. Only
   where there is room for all three; below 1100px both readings stack the
   same way. The cards align to the top, because a card centred on the row
   grows upward when a panel opens and drags its own button away from the
   pointer that just pressed it. */
@media (min-width:1101px){
  [data-aclayout="beside"] .ac-stage{display:grid;max-width:1440px;
    grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
    align-items:start;column-gap:clamp(20px,2.4vw,44px)}
  [data-aclayout="beside"] .ac-cards{display:contents}
  /* the logo spans the same four rows the two cards share, so the cards keep one
     subgrid either side of it: equal, and every row level */
  [data-aclayout="beside"] .lvl-slot:nth-child(1){grid-column:1;grid-row:1 / span 4;justify-self:end}
  [data-aclayout="beside"] .ac-core{grid-column:2;grid-row:1 / span 4}
  [data-aclayout="beside"] .lvl-slot:nth-child(2){grid-column:3;grid-row:1 / span 4;justify-self:start}
  [data-aclayout="beside"] .lvl-slot{width:min(100%,calc(var(--k-lvl-w) * 1px));
    margin-top:clamp(20px,4vh,56px)}
  [data-aclayout="beside"] .ac-title span{
    font-size:min(calc(var(--k-ac-title-side) * 1vw),calc(var(--k-ac-title-max) * 1rem))}
  /* The cards stand where the credits run, so the credits start at the card's
     edge: behind a card where the two meet, and never as stray letters in the
     strip between the card and the edge of the screen. */
  [data-aclayout="beside"] .roll{padding-left:var(--gutter)}
  [data-aclayout="beside"] .roll-col.r .roll{padding-right:var(--gutter)}
}

@media (max-width:1100px){
  :root{--k-credits-fs:20}
  .ac-cards{grid-template-columns:minmax(0,min(100%,560px))}
  .ac-pending{max-width:560px}
  .roll-col{width:min(17vw,200px)}
}
@media (max-width:720px){
  /* the gutters on a phone are a few pixels wide, so there is nowhere for the
     credits to stand without running behind the cards */
  .credits{display:none}
  .ac-mark{width:min(40vw,176px)}
  .ac-title span{font-size:clamp(1.9rem,10.4vw,3.6rem)}
}

/* ---- the channel's own action ----
   Gold and filled, because it is the one thing to do in this section and the
   nav's CONTACT is an outline: two outlines on one screen read as equals and
   neither leads. Sized off the Academy's card button so the two sections'
   actions are the same object. */
.ch-join{margin-top:clamp(30px,4.6vh,54px);display:flex;flex-direction:column;
  /* the gap clears the slot's own label chip, which sits 8px above its box */
  align-items:center;gap:16px;padding:0 var(--gutter)}
.joinbtn{display:inline-flex;align-items:center;justify-content:center;gap:12px;
  min-width:clamp(200px,20vw,268px);
  padding:clamp(14px,1.9vh,19px) clamp(30px,3.6vw,52px);
  border:1px solid var(--k-gold);border-radius:999px;
  background:var(--k-gold);color:#141008;
  font-size:clamp(12px,1.02vw,14.5px);font-weight:600;
  letter-spacing:.17em;text-transform:uppercase;white-space:nowrap;
  box-shadow:0 14px 30px -14px rgba(225,168,78,.7);
  translate:calc(var(--k-off-chjoin-x) * 1px) calc(var(--k-off-chjoin-y) * 1px);
  transition:background .25s,border-color .25s,box-shadow .25s,transform .25s var(--ease)}
.joinbtn::after{content:"";width:6px;height:6px;flex:none;
  border-top:1.5px solid currentColor;border-right:1.5px solid currentColor;
  transform:rotate(45deg);transition:transform .25s var(--ease)}
.joinbtn:hover{background:var(--k-gold-light);border-color:var(--k-gold-light);
  box-shadow:0 18px 38px -14px rgba(243,217,106,.8)}
.joinbtn:hover::after{transform:translateX(3px) rotate(45deg)}
.joinbtn:focus-visible{outline:2px solid var(--k-gold-light);outline-offset:4px}
/* the missing destination is still marked, but as one quiet line rather than a
   boxed slot: a dashed panel under a CTA makes the CTA read as the gap. The
   boxed slots in this section are whole missing blocks; this is one href. */
.join-note{margin:0;text-align:center;font-size:10px;letter-spacing:.13em;
  text-transform:uppercase;color:#7e786d;max-width:44ch;line-height:1.9}
.join-note::before{content:"";display:inline-block;width:5px;height:5px;
  margin-right:8px;border-radius:50%;background:var(--k-gold);
  vertical-align:middle;opacity:.8}

/* it arrives with the rest of the section, on the same clock, by clip */
.channel .ch-join{transition:clip-path calc(.8s * var(--k-anim))
  calc(.34s * var(--k-anim)) var(--ease),
  transform calc(.8s * var(--k-anim)) calc(.34s * var(--k-anim)) var(--ease)}
.channel:not(.seen) .ch-join{clip-path:inset(calc(100% + 26px) -26px -26px -26px);
  transform:translateY(14px)}
.channel.seen .ch-join{clip-path:inset(-26px);transform:none}

/* ================= about ================= */
/* The direction ABR chose, 05 Emblem, on its reference the Eladio Dieste
   site: after the hero a rule (the section's hairline, as on every section
   here), then one huge paragraph across the width, a smaller block set to the
   right, and a row of three photographs. Left-aligned on purpose: it is a
   statement, not a centred heading like the offers below it. */
.about{position:relative;z-index:2;background:var(--k-black);
  padding:clamp(64px,11vh,132px) var(--gutter) clamp(64px,10vh,120px);
  border-top:1px solid rgba(225,168,78,.13)}
.ab-inner{max-width:1180px;margin:0 auto}
.ab-eyebrow{translate:calc(var(--k-off-abeyebrow-x) * 1px) calc(var(--k-off-abeyebrow-y) * 1px)}
.ab-text{margin-top:clamp(14px,2.2vh,26px);
  font-size:clamp(calc(var(--k-about-fs-min) * 1px),calc(var(--k-about-fs) * 1vw),calc(var(--k-about-fs-max) * 1rem));
  font-weight:600;font-variation-settings:'wdth' 100;line-height:1.14;letter-spacing:-.012em;
  color:var(--k-bone);text-wrap:pretty;
  translate:calc(var(--k-off-abtext-x) * 1px) calc(var(--k-off-abtext-y) * 1px)}
/* ---- the five pillars, four ways, while Ghady picks (data-abhl) ----
   He did not like the gold marker (2026-09-15). plain sets them like the rest
   of the paragraph; gold sets them in the logo's gold; roll is gold with his
   saved Random Letter Swap under the pointer; scroll is Momento's About, the
   paragraph lighting from grey to white word by word as it is read. The
   letter copies exist in every treatment and show only in roll. */
.ab-p .lr{display:none}
[data-abhl="gold"] .ab-p,[data-abhl="roll"] .ab-p{color:var(--k-gold)}
/* roll: every letter is a window with its twin waiting underneath. Under the
   pointer the pair rises one letter after another and settles back when the
   pointer leaves. The real words stay in the page, out of sight, for screen
   readers and copying; the letters are hidden from assistive technology. The
   hidden words sit in a 1px box at the paragraph's own corner (its translate
   makes it their containing block): left as one line beside a pillar near the
   end of a line, they ran past the right edge of the screen at 26 of 28 sizes. */
[data-abhl="roll"] .ab-p .t{position:absolute;left:0;top:0;width:1px;height:1px;
  overflow:hidden;opacity:0;pointer-events:none}
[data-abhl="roll"] .ab-p .lr{display:inline}
.ab-p .wd{white-space:nowrap}
/* The window is overflow. Overflow moves an inline-block's baseline to its bottom edge,
   so the letters are aligned by their top instead; the box is exactly one line tall, so
   each letter sits on the baseline of the words beside it (measured 0px). */
.ab-p .l{display:inline-block;overflow:hidden;vertical-align:top}
.ab-p .l > span{display:block;position:relative;
  transition:transform calc(.46s * var(--k-anim)) calc(var(--li,0) * 18ms) var(--ease)}
.ab-p .l > span::after{content:attr(data-ch);position:absolute;left:0;top:100%}
@media (hover:hover){
  [data-abhl="roll"] .ab-p:hover .l > span{transform:translateY(-100%)}
}
/* scroll: a colour, never an opacity. The dim state is #6b675f on black,
   3.7:1, above what large type needs, so no word is ever unreadable. */
[data-abhl="scroll"] .ab-text .sw{color:#6b675f;transition:color calc(.4s * var(--k-anim)) var(--ease)}
[data-abhl="scroll"] .ab-text .sw.on{color:var(--k-bone)}
.ab-aside{margin:clamp(34px,6vh,80px) 0 0 auto;max-width:46ch;
  translate:calc(var(--k-off-abaside-x) * 1px) calc(var(--k-off-abaside-y) * 1px)}
.ab-aside .slot{display:block;max-width:none;margin-top:0}
.ab-photos{margin-top:clamp(30px,4.4vh,52px);display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(14px,1.8vw,24px);
  translate:calc(var(--k-off-abphotos-x) * 1px) calc(var(--k-off-abphotos-y) * 1px)}
/* The frames are marked like every other gap the team owes. A photograph of a
   person is never stood in for, and the permission has to come from ABR. */
.ab-ph{position:relative;aspect-ratio:var(--k-about-ph);border-radius:10px;
  border:1px dashed rgba(225,168,78,.38);
  background:repeating-linear-gradient(135deg,transparent 0 12px,rgba(242,239,232,.03) 12px 13px),#0b0b0c;
  display:flex;align-items:flex-end;justify-content:flex-end;padding:14px 16px}
.ab-ph::before{content:attr(data-slot);position:absolute;top:-8px;left:12px;
  background:var(--k-black);padding:0 7px;
  font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--k-gold)}
.ab-ph span{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#8d877c}

/* ---- the entrance: clip and transform, never opacity on type. The start
   clip reaches past the bleed, so nothing shows as a line before it arrives. */
.about .ab-eyebrow,.about .ab-text,.about .ab-aside,.about .ab-photos{
  transition:clip-path calc(.9s * var(--k-anim)) var(--ad,0ms) var(--ease),
             transform calc(.9s * var(--k-anim)) var(--ad,0ms) var(--ease)}
.about:not(.seen) .ab-eyebrow,.about:not(.seen) .ab-text,
.about:not(.seen) .ab-aside,.about:not(.seen) .ab-photos{
  clip-path:inset(0 -24px calc(100% + 24px) -24px);transform:translateY(16px)}
.about.seen .ab-eyebrow,.about.seen .ab-text,.about.seen .ab-aside,.about.seen .ab-photos{
  clip-path:inset(-24px);transform:none}
.about .ab-text{--ad:calc(.12s * var(--k-anim))}
.about .ab-aside{--ad:calc(.9s * var(--k-anim))}
.about .ab-photos{--ad:calc(1.05s * var(--k-anim))}

@media (max-width:720px){
  .ab-aside{max-width:none;margin-left:0}
  .ab-photos{grid-template-columns:1fr 1fr}
  .ab-ph:last-child{grid-column:1/-1;aspect-ratio:16/10}
}

/* ================= feedback ================= */
/* Two categories, one fan. The split is the structure: a switch under the
   offers' own names picks which offer's feedback is dealt, so a visitor cannot
   mistake one for the other. Frames are empty and marked until the team sends
   the screenshots. */
.feedback{position:relative;z-index:2;background:var(--k-black);
  padding:clamp(74px,11vh,132px) 0 clamp(70px,10vh,120px);
  overflow:hidden}
.fb-head{padding:0 var(--gutter);text-align:center}
.fb-title{translate:calc(var(--k-off-fbtitle-x) * 1px) calc(var(--k-off-fbtitle-y) * 1px)}
.fb-title span{display:inline-block;
  font-size:clamp(2rem,4.4vw,3.6rem);font-weight:800;
  font-variation-settings:'wdth' 104;letter-spacing:.005em;line-height:1.05;
  text-transform:uppercase;
  background-image:var(--type-sweep),var(--type-gold);
  background-size:280% 100%,100% 100%;background-repeat:no-repeat,no-repeat;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  text-shadow:0 0 calc(30px * var(--k-glow)) rgba(203,148,58,.30);
  animation:sheen 7.5s linear infinite}
.fb-desc{margin-left:auto;margin-right:auto;display:inline-block}

.fb-item{position:absolute;inset:0;border-radius:10px;
  background:var(--plate-face);box-shadow:var(--plate-shadow);
  display:flex;align-items:center;justify-content:center}
.fb-item::before{content:"";position:absolute;inset:0;border-radius:inherit;
  background:var(--plate-edge);opacity:.6;pointer-events:none}
/* the empty state: a marked frame, not a fake screenshot */
.fb-item.is-empty{background:rgba(255,255,255,.014);
  border:1px dashed rgba(225,168,78,.34);box-shadow:none}
.fb-item.is-empty::before{display:none}
.fb-item .fb-mark{font-size:9px;letter-spacing:.17em;text-transform:uppercase;
  color:var(--k-gold);opacity:.75;text-align:center;padding:0 14px;line-height:1.9}
.fb-item .fb-mark b{display:block;font-weight:400;color:#7e786d;font-size:8.5px;
  letter-spacing:.14em}
.fb-item img{width:100%;height:100%;object-fit:cover;border-radius:inherit;display:block}

.fb-community{margin:clamp(38px,5.5vh,64px) auto 0;padding:0 var(--gutter);
  max-width:560px;text-align:center;
  translate:calc(var(--k-off-fbcommunity-x) * 1px) calc(var(--k-off-fbcommunity-y) * 1px)}
.fb-comm-k{font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--k-gold);margin-bottom:6px}
.fb-comm-t{font-size:clamp(17px,1.7vw,23px);font-weight:700;color:var(--k-bone);
  letter-spacing:.01em}
.fb-comm-slot{margin-top:14px}

/* ---- the entrance. Clip and transform, never opacity on type, and both
   selectors always so ?still=1 lands the finished state. ---- */
.feedback .fb-title span,
.feedback .fb-desc,.feedback .fb-community{
  transition:clip-path calc(.8s * var(--k-anim)) var(--ease),
             transform calc(.8s * var(--k-anim)) var(--ease)}
.feedback:not(.seen) .fb-title span{clip-path:inset(0 0 calc(100% + 24px) 0)}
.feedback:not(.seen) .fb-desc,
.feedback:not(.seen) .fb-community{clip-path:inset(calc(100% + 24px) 0 0 0);
  transform:translateY(14px)}
.feedback.seen .fb-title span,.feedback.seen .fb-desc,
.feedback.seen .fb-community{
  clip-path:inset(-24px);transform:none}
.feedback .fb-desc{transition-delay:calc(.12s * var(--k-anim))}
.feedback .fb-community{transition-delay:calc(1.08s * var(--k-anim))}

/* ================= feedback, the fan =================
   On Ghady's pick of 2026-09-14, and the only layout since 2026-09-15, when it
   replaced the two rails. Anchored to Ghady's saved Card Fan Carousel: cards
   fanned along an arc, the front one upright and largest, an elastic deal on
   arrival, the fan opening under the pointer, pagination that wraps round. The
   categories stay two: the switch picks which offer's feedback is dealt.
   Every card's place is two numbers from the script: --d, its signed distance
   from the front card measured round the circle so the fan always balances, and
   --ad, the same without the sign. The arc is written once, here. */
.fb-fan{margin-top:clamp(28px,4.2vh,50px);
  translate:calc(var(--k-off-fbfan-x) * 1px) calc(var(--k-off-fbfan-y) * 1px)}

.fb-switch{display:flex;justify-content:center;flex-wrap:wrap;gap:10px;padding:0 var(--gutter)}
.fb-tab{display:inline-flex;align-items:baseline;gap:10px;cursor:pointer;
  font-family:inherit;font-size:clamp(13px,1.05vw,15px);font-weight:700;letter-spacing:.03em;
  color:var(--k-bone);background:transparent;
  border:1px solid rgba(244,242,236,.22);border-radius:999px;padding:12px 22px;
  transition:background .25s,border-color .25s,color .25s}
.fb-tab small{font-size:9px;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:#8d877c;transition:color .25s}
.fb-tab:hover{border-color:var(--k-gold-light);color:var(--k-gold-light)}
.fb-tab[aria-selected="true"]{background:var(--k-gold);border-color:var(--k-gold);color:#141008}
.fb-tab[aria-selected="true"] small{color:rgba(20,16,8,.62)}
.fb-tab:focus-visible{outline:2px solid var(--k-gold-light);outline-offset:3px}

.fb-stage{position:relative;overflow:hidden;touch-action:pan-y;
  height:calc(var(--k-fan-h) * 1px + var(--k-fan-drop) * 3px + 60px);
  margin-top:clamp(16px,2.8vh,32px);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.fb-panel{position:absolute;inset:0}
.fb-panel[hidden]{display:none}
.fb-deck{list-style:none;position:absolute;inset:0;--open:1}
@media (hover:hover){
  .fb-stage:hover .fb-deck{--open:var(--k-fan-open)}
}
.fb-card{position:absolute;left:50%;top:22px;cursor:pointer;
  width:calc(var(--k-fan-h) * var(--k-fb-ratio) * 1px);height:calc(var(--k-fan-h) * 1px);
  margin-left:calc(var(--k-fan-h) * var(--k-fb-ratio) * -.5px);
  transform-origin:50% 100%;
  transform:translateX(calc(var(--d,0) * var(--k-fan-spread) * var(--open) * 1px))
            translateY(calc((var(--ad,0) * var(--ad,0) + var(--ad,0)) * var(--k-fan-drop) * .5px))
            rotate(calc(var(--d,0) * var(--k-fan-angle) * 1deg))
            scale(calc(1 - var(--ad,0) * var(--k-fan-shrink)));
  z-index:calc(20 - var(--ad,0));
  transition:transform calc(.62s * var(--k-anim)) calc(var(--ad,0) * 30ms * var(--k-anim))
             cubic-bezier(.22,1.25,.36,1)}
.fb-card.is-front{cursor:default}
.fb-card.is-far{visibility:hidden}
.fb-card .fb-item{
  transition:border-color .3s,background .3s,filter .3s,box-shadow .3s,
             clip-path calc(.5s * var(--k-anim)) calc((.2s + var(--ad,0) * 70ms) * var(--k-anim)) var(--ease)}
.fb-card:not(.is-front) .fb-item{filter:brightness(.7)}
/* In a fan the cards lie over each other, so an empty frame needs a ground of its
   own. The frame's near-transparent empty fill, which suited the rails where
   nothing overlapped, let every edge and label behind show through the front card
   in the first render. */
.fb-card .fb-item.is-empty{background:linear-gradient(180deg,#141415,#0b0b0c);
  box-shadow:0 26px 50px -22px rgba(0,0,0,.95)}
.fb-card.is-front .fb-item.is-empty{border-color:rgba(243,217,106,.58);
  background:linear-gradient(180deg,#19191a,#0e0e0f)}
.fb-card.is-front .fb-item:not(.is-empty){
  box-shadow:0 30px 60px -20px rgba(0,0,0,.85),0 0 calc(34px * var(--k-glow)) -8px rgba(225,168,78,.45)}
/* a switch of category deals the fan again from a stack */
.fb-deck.is-stacked .fb-card{transform:translateY(60px) scale(.9);transition:none}

.fb-nav{display:flex;align-items:center;justify-content:center;gap:14px;
  margin-top:clamp(4px,1vh,12px);padding:0 var(--gutter)}
.fb-prev,.fb-next{position:relative;flex:none;width:44px;height:44px;padding:0;cursor:pointer;
  border-radius:50%;border:1px solid rgba(244,242,236,.22);background:transparent;color:var(--k-bone);
  transition:border-color .25s,color .25s}
.fb-prev::before,.fb-next::before{content:"";position:absolute;left:50%;top:50%;width:8px;height:8px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor}
.fb-prev::before{transform:translate(-30%,-50%) rotate(135deg)}
.fb-next::before{transform:translate(-70%,-50%) rotate(-45deg)}
.fb-prev:hover,.fb-next:hover{border-color:var(--k-gold-light);color:var(--k-gold-light)}
.fb-prev:focus-visible,.fb-next:focus-visible,.fb-dot:focus-visible{
  outline:2px solid var(--k-gold-light);outline-offset:3px}
.fb-dots{display:flex;align-items:center}
/* the dot is 24px wide and 44px tall to touch, and 7px to see: the audit holds a
   tap target on a phone to 34px tall, and a row of five still fits a 320px screen */
.fb-dot{position:relative;width:24px;height:44px;padding:0;border:0;background:none;cursor:pointer}
.fb-dot::before{content:"";position:absolute;left:50%;top:50%;width:7px;height:7px;
  margin:-3.5px 0 0 -3.5px;border-radius:999px;background:rgba(244,242,236,.28);
  transition:width .3s var(--ease),margin .3s var(--ease),background .3s}
.fb-dot[aria-current="true"]::before{width:20px;margin-left:-10px;background:var(--k-gold)}

/* the entrance: the switch and the controls rise by clip like the title, and the
   fan deals out from a stack, elastic, the front card first */
.feedback .fb-switch,.feedback .fb-nav{
  transition:clip-path calc(.8s * var(--k-anim)) calc(.2s * var(--k-anim)) var(--ease),
             transform calc(.8s * var(--k-anim)) calc(.2s * var(--k-anim)) var(--ease)}
.feedback .fb-nav{transition-delay:calc(.9s * var(--k-anim))}
.feedback:not(.seen) .fb-switch,.feedback:not(.seen) .fb-nav{
  clip-path:inset(calc(100% + 24px) -24px -24px -24px);transform:translateY(14px)}
.feedback.seen .fb-switch,.feedback.seen .fb-nav{clip-path:inset(-24px);transform:none}
.feedback:not(.seen) .fb-card{transform:translateY(60px) scale(.9)}
.feedback:not(.seen) .fb-card .fb-item{clip-path:inset(calc(100% + 26px) -26px -26px -26px)}
.feedback.seen .fb-card .fb-item{clip-path:inset(-26px)}

@media (max-width:720px){
  :root{--k-fan-h:340;--k-fan-spread:96;--k-fan-angle:6;--k-fan-drop:18}
  .fb-tab{padding:11px 16px}
  .fb-tab small{display:none}
}
/* a short screen gets a shorter card, whatever its width */
@media (max-height:560px){
  :root{--k-fan-h:250;--k-fan-drop:14}
}

/* ================= the legal slot ================= */
/* Not decoration and not a copy decision: CLAUDE.md section 3 requires
   the risk paragraph on the page. It is set quietly, in the same black,
   so the landing still reads as one screen. */
.legal{position:relative;z-index:2;background:var(--k-black);
  padding:clamp(26px,5vh,54px) var(--gutter) clamp(30px,6vh,60px);
  border-top:1px solid rgba(225,168,78,.13)}
/* It is the only thing under the fold, so it arrives when it is reached
   rather than having already happened. The rule above it draws first.
   .seen is set by an observer in site.js; ?still= and reduced motion both
   land it immediately. */
.legal{--lg:calc(.85s * var(--k-anim))}
.legal::before{content:"";position:absolute;left:0;right:0;top:-1px;height:1px;
  background:linear-gradient(90deg,transparent,rgba(225,168,78,.55) 50%,transparent);
  transform:scaleX(0);transition:transform var(--lg) var(--ease)}
.legal p{clip-path:inset(0 0 100% 0);transform:translateY(12px);
  transition:clip-path var(--lg) calc(.14s * var(--k-anim)) var(--ease),
             transform var(--lg) calc(.14s * var(--k-anim)) var(--ease)}
.legal.seen::before,.still .legal::before{transform:scaleX(1)}
.legal.seen p,.still .legal p{clip-path:inset(0 0 -40% 0);transform:none}
.legal p{max-width:74ch;margin:0 auto;text-align:center;
  font-size:clamp(10.5px,.78vw,12px);line-height:1.85;letter-spacing:.035em;
  color:#8e887c}
.legal .slot{display:block;margin-top:12px;font-size:9.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--k-gold-deep);opacity:.7}

/* ================= responsive ================= */
@media (max-width:1100px){
  .nav{grid-template-columns:auto 1fr;row-gap:14px}
  .menu{grid-column:1/-1;order:3;justify-content:center}
  .pill{grid-column:2;justify-self:end}
}
/* Above about 2000px wide the screen keeps growing and the composition stops:
   the mark is held at its 300px cap and the name at its 6.6rem one, so a
   2560x1440 screen has far more height than the stack can ever use and the
   spare lands under the button however it is shared out. The caps go up on
   those screens only, so 1920 and everything below is untouched, and the svh
   cap on the mark still holds it down on a wide screen that is short. */
@media (min-width:2000px){
  :root{--k-mark-max:420;--k-name-max:8.6;--k-facts:15}
}
/* A tablet held upright is the one shape where the mark is set by width and
   the screen is long: 20.5vw of an 834px iPad is a 171px logo on a 1112px
   screen, so the stack cannot fill what it is given and the rest of the hero
   is air however it is distributed. The mark is the subject here exactly as it
   is on a phone, where this was already answered with --k-mark:42. */
@media (min-width:721px) and (max-width:1100px) and (min-height:900px){
  :root{--k-mark:31}
}
/* Under about 880px the five facts there used to be could not hold one row,
   so they had a stated grid, three then two. The four since 2026-09-15 fit one
   row down to 721px (36px to spare at 721, measured with the webfont), so this
   range keeps the desktop row and is told not to wrap, because a wrapped flex
   row has no row gap and keeps its dividers. The padding floor comes down a
   little to buy margin at the narrow end; the items still share the row out
   evenly, so what you see barely moves. */
@media (min-width:721px) and (max-width:880px){
  .facts{flex-wrap:nowrap}
  .facts .f{padding:0 clamp(10px,1.6vw,30px)}
}
@media (max-width:720px){
  /* the mark is the subject, and 24vw of a phone is a sticker */
  :root{--k-mark:42;--k-horizon:20;--hero-top:clamp(96px,13.5vh,140px)}
  /* .horizon used to re-declare --band-h here with a hardcoded 20vh and no
     floor. It computed the same as :root only because the width cap happened
     to bind at phone widths; above about 430px wide with a short viewport the
     two drifted, so the motif sat in a band taller than itself, and any
     override of --k-horizon reached the padding but not the art. One value
     drives both, as documented, so the override is gone. */
  .name span{white-space:normal;font-size:clamp(2.05rem,11.2vw,3.4rem);line-height:1.03}
  /* Clip, not visible. The mask is what hides the name while it is parked
     at translateY(108%) waiting to rise; with overflow:visible the phone
     showed the whole wordmark sitting a line lower over the facts for the
     length of the entrance. It was set to visible because line-height 1.03
     crops the tops of the caps, so the clip keeps a small bleed instead of
     being switched off. */
  .name{overflow:clip;overflow-clip-margin:.16em}
  /* two columns and no rules: wrapped flex left a stray full-height line
     down the middle of the block */
  .facts{display:grid;grid-template-columns:1fr 1fr;
    gap:clamp(10px,2.2vh,16px) 8px;width:100%;max-width:400px;
    margin-top:clamp(14px,2.4vh,24px)}
  .cta{margin-top:clamp(14px,2.4vh,26px)}
  .facts .f{padding:0 6px}
  .facts .f + .f::before{display:none}
  .facts .t{font-size:10px;letter-spacing:.14em;white-space:normal;text-align:center}
  .menu{gap:14px}
  .menu a{font-size:11px;letter-spacing:.12em}
}
/* ================= the lab ================= */
/* Only ever on when site/lab has framed this page and move mode is on. */
body[data-lab-move="1"] [data-move]{cursor:grab;outline:1px dashed rgba(225,168,78,.55);
  outline-offset:6px;pointer-events:auto}
body[data-lab-move="1"] [data-move]:hover{outline-color:var(--k-gold-light)}
body[data-lab-move="1"] [data-move].picked{outline:1.5px solid var(--k-gold-light);
  outline-offset:6px;cursor:grabbing}
body[data-lab-move="1"] .horizon{pointer-events:auto}

/* ================= short viewports =================
   The hero is one screen by contract, so its stack has to fit the height it
   is given and not only the width. It did not: every viewport under about
   700px tall overflowed, and in most of them the CONTACT button crossed into
   the foot band, which is the one thing the band rule exists to stop. Broken
   were landscape phones (844x390, 740x360, 640x360), short laptops
   (1024x600) and short phones (360x640, 375x667).

   Width-based rules could never have caught it, because 844x390 is a wide
   viewport. These are keyed on height and apply at any width.

   The nav is the reason the padding-top floors look large: it is fixed, so
   the hero's top padding is what keeps the mark out from under it. Shrink one
   and the other has to come with it. */
@media (max-height:760px){
  :root{--k-mark-vh:21;--k-horizon:15;--k-band-min:104;
        --hero-top:clamp(60px,8.5vh,100px);--hero-safe:clamp(6px,1.1vh,12px)}
  .nav{padding:clamp(9px,1.4vh,16px) var(--gutter)}
  .lockup .mk{width:clamp(34px,3.6vw,50px)}
  .facts{margin-top:clamp(8px,1.6vh,20px)}
  .cta{margin-top:clamp(8px,1.7vh,22px)}
  .cta .pill{padding:clamp(11px,1.8vh,17px) clamp(34px,4.4vw,62px)}
}
/* Recover the row the nav spends on wrapping, once there is width for it.
   Below 1100px wide the menu drops to its own line, which costs a whole row
   of a screen that has none to spare. */
/* 620 is where the lockup, four nav items and the button genuinely fit one
   row. Lower than that they do not: the button ran off the right edge, which
   is a worse fault than the row it was trying to save. */
@media (max-height:760px) and (min-width:620px){
  .nav{grid-template-columns:1fr auto 1fr;row-gap:0;gap:10px}
  .menu{grid-column:auto;order:0;flex-wrap:nowrap;gap:clamp(10px,1.8vw,46px)}
  .menu a{white-space:nowrap}
  .nav > .pill{grid-column:auto;justify-self:end}
}
/* Landscape phones. The mark gives first: at this height it is by far the
   tallest thing in the stack. */
@media (max-height:540px){
  :root{--k-mark-vh:15;--k-horizon:12;--k-band-min:70;
        --k-name:4.4;--k-name-max:3.2;--k-facts:11;
        --hero-top:clamp(38px,9vh,64px);--hero-safe:clamp(4px,.9vh,9px)}
  .facts{margin-top:clamp(5px,1.2vh,12px)}
  .cta{margin-top:clamp(5px,1.3vh,14px)}
  .cta .pill{padding:9px clamp(28px,3.8vw,48px)}
  .facts svg{width:clamp(16px,1.5vw,21px)}
  .facts .f{gap:clamp(4px,.9vh,8px)}
}
/* A landscape phone is wide enough for the facts to stay on one line,
   and two stacked rows of them is height it does not have. */
@media (max-height:540px) and (min-width:500px){
  .facts{display:flex;width:min(100%,calc(var(--k-facts-w) * 1vw));max-width:none}
  .facts .f + .f::before{display:block}
  /* and the name goes back on one line. Below 720px WIDE it is set to wrap at
     11.2vw, which is right for a phone held upright and wrong for the same
     phone turned sideways: at 640x360 that was 54px type over two lines, 115px
     of a 360px screen. Width alone cannot tell those two cases apart. */
  .name span{white-space:nowrap;line-height:1;
    font-size:min(calc(var(--k-name) * 1vw),calc(var(--k-name-max) * 1rem))}
}
/* A small phone that is also short (320x568, 360x640). The facts are the
   tallest block in the stack there, two rows of icon over label, so they are
   what gives; the mark only comes down enough to pay the rest. */
@media (max-height:700px) and (max-width:430px){
  :root{--k-mark-vh:16}
  .facts{gap:clamp(5px,1.1vh,9px) 6px}
  .facts .f{gap:clamp(3px,.7vh,6px)}
  .facts svg{width:18px}
}

/* Under 400px tall is a squashed browser window rather than a device, but it
   should still hold together. The facts and the band are the last two things
   with any room left to give. */
@media (max-height:400px){
  :root{--k-band-min:58;--k-mark-vh:14}
  .facts svg{width:15px}
  .facts .f{gap:3px}
  .facts .t{font-size:9px;letter-spacing:.1em}
}

/* Very narrow: a Galaxy Fold's cover screen is 280px. The lockup and the
   button alone are wider than that at their normal size, so the button hung
   off the right edge. Everything in the nav comes down together. */
@media (max-width:340px){
  :root{--gutter:10px}
  .nav{gap:8px}
  .lockup{gap:7px}
  .lockup .mk{width:30px}
  .lockup .wm b{font-size:13px;letter-spacing:.03em}
  .lockup .wm i{font-size:7px;letter-spacing:.28em}
  /* width is what is scarce on a 280px screen, not height, so the button pays
     in letters rather than in the 30px tall tap target it had */
  .nav > .pill{font-size:9px;letter-spacing:.07em;padding:14px 13px}
  .menu{gap:7px}
  .menu a{font-size:9px;letter-spacing:.04em}
}
/* Short AND narrow: an old small phone upright. The mark is the only thing
   left with room to give without the type going under 9px. */
@media (max-height:520px) and (max-width:430px){
  :root{--k-mark-vh:13}
}
/* Short AND wide enough: an old phone on its side. Shrinking the nav's type
   is what buys the single row here, and the row is worth about 40px of a
   320px screen. */
@media (max-height:400px) and (min-width:500px){
  .nav{grid-template-columns:1fr auto 1fr;row-gap:0;gap:8px}
  .menu{grid-column:auto;order:0;flex-wrap:nowrap;gap:10px}
  .menu a{font-size:9px;letter-spacing:.05em;white-space:nowrap}
  .nav > .pill{grid-column:auto;justify-self:end;
    font-size:9px;letter-spacing:.07em;padding:8px 14px}
  .lockup .mk{width:26px}
  .lockup .wm b{font-size:12px;letter-spacing:.03em}
  .lockup .wm i{font-size:6.5px;letter-spacing:.24em}
}

/* A narrow phone: the four nav items wrap to two lines at 320px, which costs a
   whole row on the screen with the least to spare. Tighten them instead. */
@media (max-width:380px){
  .menu{gap:9px}
  .menu a{font-size:10px;letter-spacing:.07em}
  .lockup{gap:9px}
  .lockup .mk{width:38px}
}

/* One frame with no transitions, so site/lab's Replay can snap the page
   back to the start of the entrance instead of animating there. */
body.reset *,body.reset *::before,body.reset *::after{transition:none!important}

/* still mode does not animate, it arrives finished.
   -----------------------------------------------------------------
   `.still` is added by the script, which runs after the stylesheet has
   already painted the start state, so switching it on STARTS a transition
   rather than skipping one. Every element then took its full delay plus its
   duration to land: the CONTACT button's delay alone is 1.02s, so a capture
   taken before about two seconds got a page with no button on it. The
   promise of ?still=1 is that there is nothing to wait for, and this is what
   keeps it: no transitions, no animations, final state on the first frame.
   It covers prefers-reduced-motion too, which lands in the same class. */
body.still,body.still *,body.still *::before,body.still *::after{
  transition:none!important;animation:none!important}
/* a dialog's backdrop is not ::before or ::after, so it is named */
body.still .lvl-win::backdrop{animation:none!important}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition-duration:.01ms!important}
}
