/* ILLUSORR — the CTA system. Generated from site/buttons.html, which is the
   reference sheet and the source of truth for this file. Change the sheet
   first, then re-cut this block from it, so the two cannot disagree.

   Loaded AFTER main.css, which is where every token it reads is declared:
   --indigo --cold --ink --line --faint --cream-ink --cream-dim --cream-line.

   Loaded by 14 pages. Three controls are deliberately excluded and keep their
   own styling: .il-talk (the header pill), .il-amb (the ambience toggle) and
   .ill-totop (back to top). The collector-card CTA .gc-cta is excluded too:
   its gradient is per-rarity and .fcard[data-i="2"] matches it in the frame,
   emblem and stat bars.

   main.css still carries the superseded .fakebtn, .cta-primary and .cta-ghost
   rules. Nothing in site/ uses those class names any more, so they are dead
   rather than competing, but they are the obvious thing to edit by mistake
   when a button looks wrong. Removing them is the last step of the migration. */

/* ═══════════════════════════════════════════════════════════════════════
   ▼▼▼ COPY FROM HERE — this becomes site/assets/css/buttons.css ▼▼▼

   ILLUSORR — the CTA system. ONE button, four intents, three sizes, two
   themes. Namespaced il- so per-page case CSS cannot collide with it.

   NOT LOADED BY ANY PAGE YET. This sheet is a proposal: nothing in site/
   links buttons.css, and main.css still carries the rules below. Adopting it
   is the migration in the table further down, done one page at a time.

   It replaces fourteen separate rules in main.css that had drifted apart:
   .fakebtn, .cta-primary, .cta-ghost, .il-talk, two different .cta rules
   under #aboutRoot, .gc-cta, .rail-btn, .ct-chip, .chipset span,
   .secdrop-btn, .viewtoggle button, .vembed-cta and .fl-pill. Padding ran
   from 6/12 to 17/34, type from 10px to 12px, and hover did something
   different in almost every one. The migration table on the reference page
   maps each old class to its replacement.

   THEMING. A button reads its theme from an ancestor, never from a variant
   class, so the same markup works in a dark and a light section without
   being rewritten. Both hooks are honoured: section.light, which the site
   already uses, and [data-btn-theme="light"] for anywhere that is not a
   section. Dark is the default.

   [data-bg-theme] is the hook the SITE actually uses: nav.js reads it to
   invert the header, and the landing page marks .wwa-scroll, .whofor and
   .whofor-scroll with it on plain divs rather than sections. Honouring
   only section.light and data-btn-theme left four of the six light bands
   on the home page resolving as dark, so a ghost sat there as a pale blue
   hairline on white.

   The .is-hover / .is-active / .is-focus classes exist only so the reference
   sheet can display a state without a pointer. They share their
   declarations with the real pseudo-classes through :is(), so a state can
   never be documented as one thing and behave as another.
   ═══════════════════════════════════════════════════════════════════════ */

.il-btn{
  /* One box model for every intent and size. */
  --il-btn-py:13px; --il-btn-px:26px; --il-btn-fs:11px; --il-btn-min:44px;
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  box-sizing:border-box;
  padding:var(--il-btn-py) var(--il-btn-px);
  min-height:var(--il-btn-min);
  font-family:'Outfit',system-ui,sans-serif;
  font-size:var(--il-btn-fs);font-weight:400;
  letter-spacing:.14em;text-transform:uppercase;line-height:1;
  white-space:nowrap;text-decoration:none;text-align:center;
  border:1px solid transparent;border-radius:100px;
  background:none;cursor:pointer;
  transition:background-color .35s cubic-bezier(.16,1,.3,1),
             border-color .35s cubic-bezier(.16,1,.3,1),
             color .35s cubic-bezier(.16,1,.3,1),
             box-shadow .35s cubic-bezier(.16,1,.3,1),
             transform .35s cubic-bezier(.16,1,.3,1);
  -webkit-tap-highlight-color:transparent;
}
/* Type must not reflow the box while Outfit is still loading: the fallback
   sets this tracking wider, which visibly widened the old .il-talk pill on
   every page load. A min-width holds the box through the swap. */
.il-btn{min-width:7.6em}
.il-btn--icon,.il-btn--chip{min-width:0}

/* ── sizes ─────────────────────────────────────────────────────────────
   Three, and no more. lg for a page's single most important action, md as
   the default everywhere, sm for dense rows and the header pill. */
.il-btn--lg{--il-btn-py:17px;--il-btn-px:34px;--il-btn-fs:12px;--il-btn-min:54px}
.il-btn--sm{--il-btn-py:9px;--il-btn-px:18px;--il-btn-fs:10.5px;--il-btn-min:38px}
/* A 38px target is fine for a mouse and below the floor for a thumb. */
html[data-touch] .il-btn--sm{--il-btn-min:44px;--il-btn-py:12px}

/* ── 1. primary ────────────────────────────────────────────────────────
   Solid indigo with white ink, IDENTICAL in both themes. The old set had
   primary as white-on-dark in one place and indigo-on-light in another, so
   the same intent read as two different buttons. Indigo against white is
   4.6:1, which clears the 4.5 floor at this size. */
.il-btn--primary{background:var(--indigo);border-color:var(--indigo);color:#fff}
.il-btn--primary:is(:hover,.is-hover){
  background:#3a4fe0;border-color:#3a4fe0;color:#fff;
  box-shadow:0 12px 30px -12px rgba(76,99,255,.75);transform:translateY(-1px)}
.il-btn--primary:is(:active,.is-active){transform:translateY(0);
  box-shadow:0 4px 12px -6px rgba(76,99,255,.6);background:#3446c9}

/* ── 2. ghost, the default ─────────────────────────────────────────────
   Outline that fills on hover. This is .fakebtn's behaviour, kept because
   it was the most used and the best of the fourteen. */
.il-btn--ghost{border-color:rgba(142,162,255,.5);color:var(--cold)}
.il-btn--ghost:is(:hover,.is-hover){
  background:var(--indigo);border-color:var(--indigo);color:#fff;
  box-shadow:0 10px 26px -10px rgba(76,99,255,.7);transform:translateY(-1px)}
.il-btn--ghost:is(:active,.is-active){transform:translateY(0);background:#3446c9;border-color:#3446c9}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--ghost{
  border-color:var(--indigo);color:var(--indigo)}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--ghost:is(:hover,.is-hover){color:#fff}

/* ── 3. inverse ────────────────────────────────────────────────────────
   For photography and video, where neither theme's palette is reliable
   because the ground is an image. White ink, white hairline, fills white.
   This is what .il-talk and .vembed-cta were each doing separately. */
.il-btn--inverse{border-color:rgba(255,255,255,.38);color:#fff;
  background:rgba(8,10,20,.34);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.il-btn--inverse:is(:hover,.is-hover){background:#fff;border-color:#fff;color:#05060f;
  transform:translateY(-1px)}
.il-btn--inverse:is(:active,.is-active){transform:translateY(0);background:#e6e8f2;border-color:#e6e8f2}

/* ── 4. quiet ──────────────────────────────────────────────────────────
   Tertiary. No box at all, so it cannot compete with the two above. The
   rule replaces .cs-open and .case-all, which were bare coloured text with
   no affordance and no hit area.

   KNOWN LIMIT: the underline reveal and the data-arrow mark are both drawn
   on ::after, and an element only has one. A quiet button carrying
   data-arrow therefore shows the arrow and loses the underline, which is
   what every quiet example on this page does. Splitting one onto ::before
   would fix it; left as delivered so the sheet matches the source. */
.il-btn--quiet{--il-btn-px:0px;min-width:0;color:var(--cold);
  border-radius:0;letter-spacing:.18em}
.il-btn--quiet::after{content:'';position:absolute;left:0;right:100%;bottom:-2px;
  height:1px;background:currentColor;transition:right .4s cubic-bezier(.16,1,.3,1)}
.il-btn--quiet{position:relative}
.il-btn--quiet:is(:hover,.is-hover){color:var(--ink)}
.il-btn--quiet:is(:hover,.is-hover)::after{right:0}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--quiet{color:var(--indigo)}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--quiet:is(:hover,.is-hover){color:var(--cream-ink)}

/* ── 5. icon ───────────────────────────────────────────────────────────
   Square, circular, for a rail arrow or a back-to-top. .rail-btn was 38px,
   under the touch floor. */
.il-btn--icon{--il-btn-px:0px;width:44px;height:44px;padding:0;font-size:15px;
  letter-spacing:0;border-color:var(--line);color:var(--faint)}
.il-btn--icon:is(:hover,.is-hover){background:var(--indigo);border-color:var(--indigo);color:#fff}
.il-btn--lg.il-btn--icon{width:54px;height:54px;font-size:17px}
.il-btn--sm.il-btn--icon{width:38px;height:38px;font-size:13px}
html[data-touch] .il-btn--sm.il-btn--icon{width:44px;height:44px}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--icon{
  border-color:var(--cream-line);color:var(--cream-dim)}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--icon:is(:hover,.is-hover){color:#fff}

/* ── 6. chip ───────────────────────────────────────────────────────────
   A filter or a toggle, not a call to action: lower case, no tracking, and
   it carries a selected state. Replaces .chipset span, .ct-chip and the
   sector tag pills, which were three different sizes of the same idea. */
.il-btn--chip{--il-btn-py:8px;--il-btn-px:14px;--il-btn-fs:12px;--il-btn-min:36px;
  letter-spacing:.02em;text-transform:none;border-color:var(--line);color:var(--faint)}
html[data-touch] .il-btn--chip{--il-btn-min:44px;--il-btn-py:12px}
.il-btn--chip:is(:hover,.is-hover){color:var(--ink);border-color:rgba(142,162,255,.45)}
.il-btn--chip[aria-pressed="true"],.il-btn--chip.is-on{
  color:#05060a;background:var(--cold);border-color:var(--cold);font-weight:500}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--chip{
  border-color:var(--cream-line);color:var(--cream-dim)}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--chip:is(:hover,.is-hover){
  color:var(--cream-ink);border-color:var(--indigo)}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn--chip:is([aria-pressed="true"],.is-on){
  color:#fff;background:var(--indigo);border-color:var(--indigo)}

/* ── shared states ─────────────────────────────────────────────────── */
/* Keyboard users must be able to see where they are. Applied to every
   intent at once, so a new variant cannot forget it. */
.il-btn:is(:focus-visible,.is-focus){outline:2px solid var(--cold);outline-offset:3px}
:is(section.light,[data-btn-theme="light"],[data-bg-theme="light"]) .il-btn:is(:focus-visible,.is-focus){
  outline-color:var(--indigo)}
.il-btn[disabled],.il-btn[aria-disabled="true"]{
  opacity:.38;cursor:not-allowed;transform:none;box-shadow:none;pointer-events:none}

/* Busy, for the contact and brief submits. The label stays in place so the
   box does not resize mid-submit; the spinner takes the gap slot. */
.il-btn[aria-busy="true"]{pointer-events:none}
.il-btn[aria-busy="true"]::before{content:'';width:1em;height:1em;flex:none;
  border:1.5px solid currentColor;border-top-color:transparent;border-radius:50%;
  animation:il-btn-spin .7s linear infinite}
@keyframes il-btn-spin{to{transform:rotate(360deg)}}

/* The trailing mark is part of the component, not the copy, so no page has
   to remember to type it. */
.il-btn[data-arrow]::after{content:'↗';font-size:1.05em;line-height:1;
  letter-spacing:0;transition:transform .35s cubic-bezier(.16,1,.3,1)}
.il-btn--quiet[data-arrow]::after{position:static;height:auto;background:none;
  right:auto;left:auto;bottom:auto}
.il-btn[data-arrow]:is(:hover,.is-hover)::after{transform:translate(2px,-2px)}
.il-btn[data-arrow="right"]::after{content:'→'}
.il-btn[data-arrow="right"]:is(:hover,.is-hover)::after{transform:translateX(3px)}

@media (prefers-reduced-motion:reduce){
  .il-btn,.il-btn::after{transition-duration:.01ms!important}
  .il-btn:is(:hover,.is-hover){transform:none}
  .il-btn[aria-busy="true"]::before{animation-duration:2.4s}
}
/* A group of actions is laid out with gap, never with margins on the
   buttons, so the set survives a reorder or a deletion. */
.il-btns{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.il-btns--stack{flex-direction:column;align-items:stretch}
.il-btns--stack .il-btn{width:100%}
/* On a handset a pair of primary actions reads better stacked full width
   than side by side and truncated. */
@media (max-width:430px){
  .il-btns--fit{flex-direction:column;align-items:stretch}
  .il-btns--fit .il-btn{width:100%}
}
@media print{.il-btn{border-color:#000!important;color:#000!important;background:none!important}}
/* ═══ ▲▲▲ COPY TO HERE — end of buttons.css ▲▲▲ ═════════════════════ */

/* ── the two ID-scoped resets ──────────────────────────────────────────
   main.css carries "#aboutRoot *{box-sizing:border-box;margin:0;padding:0}"
   and the same for #workGrid. A universal selector under an id is (1,0,0),
   which outranks .il-btn at (0,1,0), so inside those two roots the pill lost
   its padding entirely and collapsed onto its label: measured 144x54 with
   padding 0 against 125px of text, which is the label touching both ends and
   the arrow sitting on the edge.

   Re-asserted here rather than by exempting .il-btn from the reset, because
   the rest of both pages is built on that reset. The icon variant sets its
   own padding:0 on purpose and has to be restated after this, or it would
   inherit the 13px the custom property carries. */
#aboutRoot .il-btn,
#workGrid .il-btn{padding:var(--il-btn-py) var(--il-btn-px)}
#aboutRoot .il-btn--icon,
#workGrid .il-btn--icon{padding:0}
