/* ============================================================
   BEINC — Framed Button  (TEMP "bn-fbtn" namespace, experimental)

   A three-layer nested construction:
     Ring   — the dashed outline. Individual dash elements, generated
              by JS so they can dissolve one after another.
     Shell  — the dark solid.
     Plate  — the cream block holding the label (and optional icon).

   ── THREE STATES ────────────────────────────────────────────
                    rest      hovered    clicked
     frame pad      0px       5px        0px
     shell pad      6px       5px        10px
     plate height   32px      24px       24px
     plate pad      16px      12px       12px
     radius         4px       8px        4px
     label roll     0         1x         2x
     icon track     cell 3    cell 2     cell 1
     ring           visible   visible    dissolved

   Hover pulls everything inward. Click lets the SHELL spring back
   out while the Plate and its contents stay tight, and the Ring
   dissolves outward.

   ── WHY THE BUTTON NEVER CHANGES SIZE ───────────────────────
   Measured per side, frame edge to text, in all three states:

     rest      0 +  6 + 16 = 22px
     hovered   5 +  5 + 12 = 22px
     clicked   0 + 10 + 12 = 22px

   All 22. The outer box is fixed and the label never moves — the
   layers just nest and unnest around it. Vertically the same:
   6+32+6, 5+5+24+5+5 and 10+24+10 all make 44.

   ── EVERYTHING IS A TRANSITION, NOTHING IS A KEYFRAME ───────
   (except the chevron's idle breathe, which is a genuine loop.)
   Transitions are reversible by nature: interrupt one halfway and
   it turns around from wherever it is. That is what makes leaving
   mid-click smooth instead of flickery. `.is-clicked` is removed
   ONLY when the pointer actually leaves — never on mouseup —
   because dropping it while still hovering would snap the button
   back to its hover look. See bn-framed-button.js.

   Type is locked at 14px because the 44px height is locked.

   Depends on: global.css (tokens) + bn-framed-button.js

   Structure (the Ring is injected by JS):
   <a class="bn-fbtn" href="#">
     <span class="bn-fbtn__shell">
       <span class="bn-fbtn__plate">
         <span class="bn-fbtn__text" data-bn-fbtn-text>Start a project</span>
       </span>
     </span>
   </a>
   ============================================================ */

.bn-fbtn {
    /* theme — override per background */
    --fbtn-frame:   var(--color-grid);        /* dashes        #444444 */
    --fbtn-shell:   var(--color-black);       /* dark solid    #262626 */
    --fbtn-plate:   var(--color-white);       /* cream block   #FFFBF0 */
    --fbtn-label:   var(--color-black2);      /* label ink     #191716 */

    /* state — every one of these is re-declared by :hover and .is-clicked */
    --fbtn-frame-pad:    0px;
    --fbtn-shell-pad:    6px;
    --fbtn-plate-h:      32px;
    --fbtn-plate-pad:    16px;
    --fbtn-pad-x:        0px;                  /* extra L/R padding — the .bn-fbtn--wide modifier bumps this */
    --fbtn-radius:       var(--radius);       /* 4px */
    --fbtn-roll-step:    0;                   /* which copy of the label shows */
    --fbtn-track-step:   0;                   /* which chevron shows */
    --fbtn-ring-out:     0px;                 /* how far the ring sits outside the box */
    --fbtn-ring-opacity: 1;

    /* fixed */
    --fbtn-ring-delay:  0.08s;                /* ring lags the Shell — see RING note */
    --fbtn-height:  44px;
    --fbtn-speed:   0.6s;
    --fbtn-ease:    var(--ease-out-expo);     /* cubic-bezier(0.16, 1, 0.3, 1) */
    --fbtn-roll:    1.3em;

    position: relative;
    display: inline-flex;
    align-items: stretch;
    box-sizing: border-box;
    height: var(--fbtn-height);
    padding: var(--fbtn-frame-pad);
    border-radius: var(--fbtn-radius);

    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;

    transition: padding var(--fbtn-speed) var(--fbtn-ease),
                border-radius var(--fbtn-speed) var(--fbtn-ease);
}


/* ── THE RING ──
   An ordinary CSS dashed border, drawn on a pseudo-element so it costs
   no layout — which is also what keeps the 44px height exact.

   Two earlier attempts are worth not repeating. One element per dash
   cannot work at this radius: a 4px corner is only 6.28px of arc, which
   is shorter than a single dash-and-gap, so corners came out as holes
   and any dash landing on one was a straight chord across 90 degrees of
   curve. An SVG stroke fixed the geometry and allowed tunable dashes,
   but the browser's own dash rhythm read better and matches the guide
   lines used elsewhere on the site — so the simplest thing won.

   `border-radius: inherit` means the outline tracks the 4px -> 8px
   corner change on hover for free.

   ON CLICK it grows outward by --fbtn-ring-out and fades, and it starts
   --fbtn-ring-delay AFTER the Shell does. That lag is the whole point:
   the Shell springs out first and the ring gives way a moment later, so
   it reads as being pushed rather than the two moving in lockstep.
   Coming back there is no delay, because the Shell's outer edge does
   not move between clicked and rest — there is nothing to be pushed by,
   so the ring simply returns. */
.bn-fbtn::before {
    content: "";
    position: absolute;
    inset: calc(0px - var(--fbtn-ring-out));
    border: var(--guide-width) var(--guide-style) var(--fbtn-frame);
    border-radius: calc(var(--fbtn-radius) + var(--fbtn-ring-out));
    opacity: var(--fbtn-ring-opacity);
    pointer-events: none;
    transition: inset var(--fbtn-speed) var(--fbtn-ease),
                border-radius var(--fbtn-speed) var(--fbtn-ease),
                opacity var(--fbtn-speed) var(--fbtn-ease);
}


/* ── SHELL ── */
.bn-fbtn__shell {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    box-sizing: border-box;
    padding: var(--fbtn-shell-pad);
    border-radius: var(--radius);
    background: var(--fbtn-shell);
    transition: padding var(--fbtn-speed) var(--fbtn-ease),
                background-color var(--fbtn-speed) var(--fbtn-ease);
}


/* ── PLATE ── */
.bn-fbtn__plate {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    height: var(--fbtn-plate-h);
    padding: 0 calc(var(--fbtn-plate-pad) + var(--fbtn-pad-x));
    border-radius: var(--radius-sm);
    background: var(--fbtn-plate);
    transition: height var(--fbtn-speed) var(--fbtn-ease),
                padding var(--fbtn-speed) var(--fbtn-ease);
}


/* ── LABEL ── */
.bn-fbtn__text {
    display: inline-block;
    overflow: hidden;              /* masks the rolling letters */
    white-space: nowrap;
    font-family: var(--font-btn);
    font-size: 14px;               /* locked — see header note */
    font-weight: var(--font-weight-btn);
    letter-spacing: -0.06em;
    color: var(--fbtn-label);

    /* 18px, NOT 17 — do not "tidy" this back.
       The Plate animates its height 32 -> 24 while the label stays centred.
       At line-height 17 the label's centre lands exactly on a device-pixel
       boundary, so the renderer snaps it 1px back and forth every frame as the
       Plate resizes (measured: 24 snap reversals) — the visible shake. 18px
       lands the glyph box cleanly on the grid, so it holds dead steady
       (0 reversals). The 16px variant uses 20px for the same reason. */
    line-height: 18px;
}

/* Words alternate travel direction by position: 1st up, 2nd down,
   3rd up... JS stamps data-dir. --fbtn-dir drives BOTH which side the
   ghosts sit on and which way the letter travels, so they can never
   fall out of sync. */
.bn-fbtn__word {
    --fbtn-dir: 1;                 /*  1 = rolls up   (ghosts below) */
    display: inline-block;
}

.bn-fbtn__word[data-dir="down"] {
    --fbtn-dir: -1;                /* -1 = rolls down (ghosts above) */
}

.bn-fbtn__space {
    display: inline-block;
    white-space: pre;
}

/* THREE COPIES OF EVERY LETTER.
   The real glyph plus TWO ghosts, painted one and two roll-distances
   away. --fbtn-roll-step picks which one is in the window: 0 shows the
   original, 1 the first ghost (hover), 2 the second (click). That is
   what lets the click be a genuine third arrival rather than a repeat
   of the second. */
.bn-fbtn__char {
    display: inline-block;
    position: relative;
    text-shadow: currentColor 0 calc(var(--fbtn-dir) * var(--fbtn-roll)),
                 currentColor 0 calc(var(--fbtn-dir) * var(--fbtn-roll) * 2);
    transform: translateY(calc(var(--fbtn-dir) * -1 * var(--fbtn-roll) * var(--fbtn-roll-step)))
               rotate(0.001deg);
    transition: transform var(--fbtn-speed) var(--fbtn-ease);
}


/* ── ICON ──
   The square sits 5px from the Plate's top, right and bottom edges in
   every state, so its size is just the Plate height minus 10 and it
   stays a perfect square without being given a number:
       rest 32-10 = 22px      hovered & clicked 24-10 = 14px

   The Plate padding deliberately does NOT animate on this variant
   (16 left / 5 right throughout) — that is what absorbs the 8px the
   square hands back and keeps the button width fixed. */
.bn-fbtn--icon .bn-fbtn__plate {
    gap: 8px;
    padding: 0 calc(5px + var(--fbtn-pad-x)) 0 calc(16px + var(--fbtn-pad-x));
}

.bn-fbtn__icon {
    display: flex;
    align-items: center;
    justify-content: flex-end;           /* parks the track on its LAST cell */
    flex: none;
    height: calc(var(--fbtn-plate-h) - 10px);
    aspect-ratio: 1;
    border-radius: 1px;
    background: var(--fbtn-label);
    color: var(--fbtn-plate);
    overflow: hidden;
    transition: height var(--fbtn-speed) var(--fbtn-ease);
}

/* THREE CHEVRONS, one per state. The track is triple width and slides
   a third at a time, so each state's chevron arrives from the left
   while the previous exits right. */
.bn-fbtn__icon-track {
    display: flex;
    flex: none;
    height: 100%;
    transform: translate(calc(var(--fbtn-track-step) * 33.3333%), 0);
    transition: transform var(--fbtn-speed) var(--fbtn-ease);
}

.bn-fbtn__arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: calc(var(--fbtn-plate-h) - 10px);
    height: 100%;
    transition: width var(--fbtn-speed) var(--fbtn-ease);
}

/* NOTHING SCALES. The chevrons are simply built at the size their state
   needs, so the swap performs the size change and no glyph is ever
   caught mid-scale. Click keeps the small one, because clicking does
   not grow the Plate or the square back. */
.bn-fbtn__arrow svg {
    display: block;
    height: auto;
}

.bn-fbtn__arrow--click svg { width: 6.4px; }
.bn-fbtn__arrow--hover svg { width: 6.4px; }
.bn-fbtn__arrow--rest  svg { width: 10px; }

/* Idle breathe — the chevron elongates ~22% and relaxes back, forever.
   Expressed in viewBox units while the resize is in CSS pixels, so the
   two are independent and it keeps the same character at either size.
   Firefox cannot animate the CSS `d` property; there it falls back to
   the `d` attribute in the markup, which is this same 0%/100% shape. */
.bn-fbtn__arrow svg path {
    fill: currentColor;
    animation: bnFbtnArrowBreathe 2.8s var(--ease-gentle) infinite;
}

@keyframes bnFbtnArrowBreathe {
    0%, 100% {
        d: path("M 4.88,1.14 L 12.52,8.28 C 12.70,8.45 12.97,8.44 13.14,8.26 L 13.76,7.60 C 13.93,7.42 14.20,7.41 14.38,7.58 L 17.41,10.41 C 17.59,10.58 17.60,10.85 17.43,11.03 L 7.21,21.98 C 7.04,22.16 6.77,22.17 6.59,22.00 L 3.56,19.17 C 3.38,19.00 3.37,18.73 3.54,18.55 L 9.12,12.56 C 9.29,12.38 9.28,12.11 9.10,11.94 L 1.45,4.81 C 1.27,4.64 1.26,4.37 1.43,4.19 L 4.26,1.16 C 4.43,0.98 4.70,0.97 4.88,1.14 Z");
    }
    50% {
        d: path("M 3.78,0.12 L 12.52,8.28 C 12.70,8.45 12.97,8.44 13.14,8.26 L 13.76,7.60 C 13.93,7.42 14.20,7.41 14.38,7.58 L 17.41,10.41 C 17.59,10.58 17.60,10.85 17.43,11.03 L 3.79,25.64 C 3.62,25.82 3.35,25.83 3.17,25.66 L 0.14,22.83 C -0.04,22.66 -0.05,22.39 0.12,22.21 L 9.12,12.56 C 9.29,12.38 9.28,12.11 9.10,11.94 L 0.35,3.79 C 0.17,3.62 0.16,3.35 0.33,3.17 L 3.16,0.14 C 3.33,-0.04 3.60,-0.05 3.78,0.12 Z");
    }
}


/* ── SIZE: 16px label ──
   Every geometric number stays as it is; only the type grows. It fits
   because a 19px line box still leaves ~2.5px of air inside the 24px
   Plate. Roll distance and tracking are em-based, so both scale with it. */
.bn-fbtn--16 .bn-fbtn__text {
    font-size: 16px;
    line-height: 20px;   /* 20 not 19 — same pixel-grid reason as the 14px label above */
}


/* ── HOVERED ──
   Gated to devices that truly hover. On touch the button rests in its
   inactive state, which is a complete design in its own right. */
@media (hover: hover) {
    .bn-fbtn:hover {
        --fbtn-frame-pad:  5px;
        --fbtn-shell-pad:  5px;
        --fbtn-plate-h:    24px;
        --fbtn-plate-pad:  12px;
        --fbtn-radius:     8px;
        --fbtn-roll-step:  1;
        --fbtn-track-step: 1;
    }
}

/* Keyboard users get the same state, plus a visible ring. Outside the
   hover query so it works on every device. */
.bn-fbtn:focus-visible {
    --fbtn-frame-pad:  5px;
    --fbtn-shell-pad:  5px;
    --fbtn-plate-h:    24px;
    --fbtn-plate-pad:  12px;
    --fbtn-radius:     8px;
    --fbtn-roll-step:  1;
    --fbtn-track-step: 1;
    outline: 2px solid var(--fbtn-plate);
    outline-offset: 3px;
}


/* ── CLICKED ──
   Declared AFTER hover and focus so it wins at equal specificity, and
   it restates EVERY value rather than inheriting from hover — that way
   a touch tap (where hover never applies) lands in exactly the same
   place as a mouse click. */
.bn-fbtn.is-clicked {
    --fbtn-frame-pad:    0px;      /* Shell springs back out to the edge */
    --fbtn-shell-pad:    10px;     /* ...but the Plate stays tight */
    --fbtn-plate-h:      24px;
    --fbtn-plate-pad:    12px;
    --fbtn-radius:       var(--radius);
    --fbtn-roll-step:    2;        /* third copy of the label rolls in */
    --fbtn-track-step:   2;        /* third chevron slides in */
    --fbtn-ring-out:     6px;      /* ring is pushed outward... */
    --fbtn-ring-opacity: 0;        /* ...and dissolves */
}

/* The lag that sells the push. Delay is taken from whichever state is
   the destination, so it applies going out and not coming back. */
.bn-fbtn.is-clicked::before {
    transition-delay: var(--fbtn-ring-delay);
}


/* ── SIZE: 52px tall (proportional) ──
   A true ~1.18x scale of the WHOLE button, not just a taller Plate: every
   nested layer — frame / shell / plate padding, radius, and the icon square
   + chevrons — grows together, so it reads as a genuinely bigger button.
   All the locked invariants still hold:
     height sums to 52 in every state
        rest   0 + 7 + 38 + 7 + 0     = 52
        hover  6 + 6 + 28 + 6 + 6     = 52
        click  0 + 12 + 28 + 12 + 0   = 52
     horizontal (frame + shell + plate-pad) = 26 per side in every state, so
     the label still never moves
        rest 0+7+19 · hover 6+6+14 · click 0+12+14   = 26
   Declared AFTER hover/focus/click so it wins at equal specificity.
   (Label line-height 18/20 stays valid — verified 0 shake at the 38->28
   Plate sweep too, because the scale keeps the glyph box on the pixel grid.) */
.bn-fbtn--52 {
    --fbtn-height:    52px;
    --fbtn-shell-pad: 7px;
    --fbtn-plate-h:   38px;
    --fbtn-plate-pad: 19px;
    --fbtn-radius:    5px;
}
@media (hover: hover) {
    .bn-fbtn--52:hover {
        --fbtn-frame-pad: 6px;
        --fbtn-shell-pad: 6px;
        --fbtn-plate-h:   28px;
        --fbtn-plate-pad: 14px;
        --fbtn-radius:    9px;
    }
}
.bn-fbtn--52:focus-visible {
    --fbtn-frame-pad: 6px;
    --fbtn-shell-pad: 6px;
    --fbtn-plate-h:   28px;
    --fbtn-plate-pad: 14px;
    --fbtn-radius:    9px;
}
.bn-fbtn--52.is-clicked {
    --fbtn-frame-pad: 0px;    /* MUST restate: this rule sits after --52:hover,
                                 so without it the hover moat (6px) leaks through
                                 on click and the shell can't fill the 52px box. */
    --fbtn-shell-pad: 12px;
    --fbtn-plate-h:   28px;
    --fbtn-plate-pad: 14px;
    --fbtn-radius:    5px;
    --fbtn-ring-out:  7px;
}

/* icon layers scale too — the base hardcodes 5px insets / 10px derivations */
.bn-fbtn--52.bn-fbtn--icon .bn-fbtn__plate { gap: 9px; padding: 0 calc(6px + var(--fbtn-pad-x)) 0 calc(19px + var(--fbtn-pad-x)); }
.bn-fbtn--52 .bn-fbtn__icon  { height: calc(var(--fbtn-plate-h) - 12px); }
.bn-fbtn--52 .bn-fbtn__arrow { width:  calc(var(--fbtn-plate-h) - 12px); }
.bn-fbtn--52 .bn-fbtn__arrow--rest  svg { width: 12px; }
.bn-fbtn--52 .bn-fbtn__arrow--hover svg,
.bn-fbtn--52 .bn-fbtn__arrow--click svg { width: 7.5px; }


/* ── SIZE: 64px tall (proportional) ──
   Same idea as --52, scaled up again (~1.45x of 44). Text stays 16px.
   Invariants hold:
     height sums to 64:  rest 0+9+46+9 · hover 7+7+36+7+7 · click 0+14+36+14
     horizontal per side = 32:  rest 0+9+23 · hover 7+7+18 · click 0+14+18 */
.bn-fbtn--64 {
    --fbtn-height:    64px;
    --fbtn-shell-pad: 9px;
    --fbtn-plate-h:   46px;
    --fbtn-plate-pad: 23px;
    --fbtn-radius:    6px;
}
@media (hover: hover) {
    .bn-fbtn--64:hover {
        --fbtn-frame-pad: 7px;
        --fbtn-shell-pad: 7px;
        --fbtn-plate-h:   36px;
        --fbtn-plate-pad: 18px;
        --fbtn-radius:    12px;
    }
}
.bn-fbtn--64:focus-visible {
    --fbtn-frame-pad: 7px;
    --fbtn-shell-pad: 7px;
    --fbtn-plate-h:   36px;
    --fbtn-plate-pad: 18px;
    --fbtn-radius:    12px;
}
.bn-fbtn--64.is-clicked {
    --fbtn-frame-pad: 0px;    /* restate (same reason as --52) so the shell fills 64 on click */
    --fbtn-shell-pad: 14px;
    --fbtn-plate-h:   36px;
    --fbtn-plate-pad: 18px;
    --fbtn-radius:    6px;
    --fbtn-ring-out:  9px;
}

.bn-fbtn--64.bn-fbtn--icon .bn-fbtn__plate { gap: 11px; padding: 0 calc(7px + var(--fbtn-pad-x)) 0 calc(23px + var(--fbtn-pad-x)); }
.bn-fbtn--64 .bn-fbtn__icon  { height: calc(var(--fbtn-plate-h) - 14px); }
.bn-fbtn--64 .bn-fbtn__arrow { width:  calc(var(--fbtn-plate-h) - 14px); }
.bn-fbtn--64 .bn-fbtn__arrow--rest  svg { width: 14px; }
.bn-fbtn--64 .bn-fbtn__arrow--hover svg,
.bn-fbtn--64 .bn-fbtn__arrow--click svg { width: 9px; }


/* ── WIDE ──
   Adds a constant L/R padding on top of whatever plate-pad the current
   size/state resolves to. Because it is the SAME extra in rest, hover
   and clicked, the locked horizontal sum still holds — the label never
   shifts, the button just gets wider. Composes with any size:
   e.g. `bn-fbtn--64 bn-fbtn--wide`. Tune the amount here. */
.bn-fbtn--wide { --fbtn-pad-x: 16px; }


/* ── REDUCED MOTION ──
   States still change, they just arrive instantly. */
@media (prefers-reduced-motion: reduce) {
    .bn-fbtn,
    .bn-fbtn__shell,
    .bn-fbtn__plate,
    .bn-fbtn__icon,
    .bn-fbtn__icon-track,
    .bn-fbtn__arrow,
    .bn-fbtn::before,
    .bn-fbtn__char {
        transition: none;
    }
    .bn-fbtn__arrow svg path {
        animation: none;
    }
}
