/* deck.css -- THE DECK'S PRESENTATION, and it is the SAME stylesheet on every
 * page that has a deck.
 *
 * WHY THIS FILE EXISTS (v3.293.0). The deck lived inside index.html's one big
 * <style>, which was correct while index.html was the only page with cards.
 * The docs door now has a deck too (his ask, 2026-08-16: "it should have its
 * own menu item with its own jittering rectangles"), and the rule is one
 * implementation per operation -- so the block MOVED here rather than being
 * copied into the door's generator (CLAUDE.md rule 33). Nothing was rewritten
 * on the way: the rules below are byte-for-byte what index.html carried at
 * v3.292.0, plus the two tokens they read.
 *
 * CONSUMERS: DOCS/Marketing/www/index.html (hand-authored) and
 * DOCS/Marketing/www/docs/index.html (GENERATED by tests/forge.cx).
 * A third consumer adds a <link>, never a second copy of these rules.
 *
 * WHAT IT ASSUMES OF ITS HOST, stated because a stylesheet that silently needs
 * things is how a skin goes wrong on the second page:
 *   - the paper palette tokens: --paper, --paper-deep, --ink, --ink-2,
 *     --hairline, --crimson. Both hosts define them.
 *   - --topbar-h, read by deck.js (not by this file) to centre the lifted card
 *     below a fixed bar. A host without one sets 0; deck.js falls back to 56.
 * The two tokens the deck OWNS are declared here, so they travel with it.
 */
/* The ARGB rotation needs a REGISTERED custom property: a plain --var cannot be
   interpolated, so `animation` on it would step rather than sweep. */
@property --argb {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

:root{
  --strip:6px;          /* LED strip thickness -- user ruling: 3x the original 2px */
  --card-r:10px;
}

/* ---- the deck: regular rectangles that drift, lift and light up ---------- */
.decksec{padding-bottom:104px}
/* The same toggle, said the way the user said it, where the irritation is. */
.stillhint{
  font-family:'Spline Sans Mono',monospace;font-size:12.5px;color:var(--ink-2);
  background:transparent;border:0;border-bottom:1px dashed var(--hairline);
  padding:0 0 1px;cursor:pointer;
}
.stillhint:hover{color:var(--crimson);border-bottom-color:var(--crimson)}
.stillhint:focus-visible{outline:3px solid var(--crimson);outline-offset:3px}

.deckhint{font-family:'Spline Sans Mono',monospace;font-size:12.5px;color:var(--ink-2);
  margin-top:-8px;margin-bottom:6px}
.deck{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:22px;
  margin-top:34px;
}
@media(max-width:1100px){ .deck{grid-template-columns:repeat(2,1fr)} }
@media(max-width:620px){ .deck{grid-template-columns:1fr} }

.card{
  position:relative;
  aspect-ratio:4 / 3;                /* REGULAR rectangles -- one shape, repeated */
  border-radius:var(--card-r);
  padding:var(--strip);              /* the strip IS the padding; the face sits inside */
  background:
    conic-gradient(from var(--argb),
      #ff0040, #ff8a00, #ffd400, #35d07f, #00c2ff, #6a5cff, #d94fff, #ff0040);
  animation:argb-idle 9s linear infinite;
  cursor:pointer;
  transition:box-shadow .25s ease, filter .3s ease, opacity .3s ease;
  box-shadow:0 10px 26px -18px rgba(22,24,26,.5);
  filter:saturate(.55);
}
.card:hover{ filter:saturate(1); box-shadow:0 16px 34px -18px rgba(22,24,26,.6) }
.card:focus-visible{ outline:3px solid var(--crimson); outline-offset:4px }
@keyframes argb-idle { to { --argb:360deg } }

.card .face{
  position:relative;height:100%;width:100%;
  border-radius:calc(var(--card-r) - 4px);   /* inner radius tracks the thicker strip */
  background:var(--paper);
  padding:22px 22px 18px;
  display:flex;flex-direction:column;
  overflow:hidden;
}
.card .n{font-family:'Spline Sans Mono',monospace;font-size:11.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--crimson)}
/* THE CARD TITLE IS A DIRECT CHILD OF THE FACE, and the selector says so
   (v3.293.0). A bare `.card h3` also matched every h3 INSIDE a card, which was
   harmless while every card body was hand-written -- and wrong the moment the
   docs door started fetching a MANUAL into one: the Language Reference's own
   headings came out at the card title's 30px, and .toc h3 with them. Direct
   child, so a nested document keeps its own type scale. */
.card > .face > h3{font-family:'Bricolage Grotesque',sans-serif;font-weight:700;font-size:22px;
  letter-spacing:-0.02em;line-height:1.12;margin:10px 0 8px;max-width:16ch}
.card .kicker{font-size:15.5px;color:var(--ink-2)}
.card .more{margin-top:auto;font-family:'Spline Sans Mono',monospace;font-size:11.5px;
  color:var(--ink-2);opacity:.85}
.card .body{display:none;margin-top:16px;font-size:17px;color:var(--ink-2);overflow:auto}
.card .body p + p{margin-top:14px}
.card .body code{font-family:'Spline Sans Mono',monospace;font-size:14px;
  background:var(--paper-deep);padding:1px 6px;border-radius:3px;color:var(--ink)}
.card .body strong{color:var(--ink);font-weight:600}
/* AND THE CHIP UNDOES ITSELF INSIDE A CODE BLOCK (v3.293.0). The rule above is
   for INLINE code -- a light chip on paper -- and it was the only kind a card
   body could contain while every card body was hand-written in index.html. The
   docs door fetches whole manuals into cards, and a manual has <pre><code>:
   measured dark ink and a light chip background ON the dark panel, i.e. an
   invisible code block, because `.card .body code` outranks a page
   stylesheet's `pre code`. Same class of leak as the card title above, same
   answer: say where the rule does NOT apply. */
.card .body pre code{background:none;padding:0;color:inherit;font-size:1em}
.card .door{
  display:inline-block;margin-top:18px;background:var(--crimson);color:#fff;
  text-decoration:none;border-radius:4px;padding:11px 20px;
  font-family:'Bricolage Grotesque',sans-serif;font-weight:700;font-size:15px;
}
.card .door:hover{filter:brightness(1.1)}
.card .door.ghost{background:transparent;color:var(--ink);border:1px solid var(--hairline)}
.card .door + .door{margin-left:10px}

/* THE FUZZLE. A card that just collided goes briefly out of focus while the JS
   adds micro-shake noise to its position. The transition is deliberately fast:
   the fuzz lasts ~300ms and the resting .3s ease would still be fading IN when
   it was time to fade out. */
.card.fuzz{ filter:saturate(.95) blur(1.6px); transition:filter .08s ease }

/* The lift. The active card leaves the grid; a dashed placeholder keeps its slot
   so the others do not reflow underneath it -- reflow under a travelling element
   is what makes this kind of animation read as broken. */
.card.active{
  position:fixed;
  z-index:60;
  margin:0;
  aspect-ratio:auto;
  animation:argb-live 2.6s linear infinite;   /* faster chase when live */
  filter:saturate(1);
  /* The scrim paints nothing now, so ALL of the separation is this shadow. Two
     layers on purpose: a tight one to read as an edge against paper, and a wide
     soft one to read as height. One layer at this size looks like a smudge. */
  box-shadow:0 6px 16px -6px rgba(22,24,26,.30),
             0 44px 100px -34px rgba(22,24,26,.60);
  transition:transform .52s cubic-bezier(.22,.9,.24,1);
  cursor:default;
}
@keyframes argb-live { to { --argb:360deg } }
.card.active .face{ padding:34px 36px 30px }
.card.active > .face > h3{ font-size:30px;max-width:22ch }
.card.active .kicker{ font-size:18px }
.card.active .more{ display:none }

/* THE EXPANDED CARD IS A READING SURFACE, AND IT HAD STOPPED BEING ONE.
   Measured at an 800x455 viewport before this fix: the body was 232px of text
   in a 168px box -- 64px simply invisible, with no scrollbar, no fade and no
   hint that anything had been cut. A flex item defaults to min-height:auto, so
   the body could not shrink to its container and the face's overflow:hidden
   quietly ate the remainder. min-height:0 is what lets it become a scroller. */
.card.active .body{
  display:block;flex:1 1 auto;min-height:0;
  overflow-y:auto;overscroll-behavior:contain;
  padding-right:16px;                     /* the bar's lane, so text never sits under it */
  scrollbar-width:thin;scrollbar-color:var(--hairline) transparent;
}
.card.active .body::-webkit-scrollbar{width:9px}
.card.active .body::-webkit-scrollbar-track{background:transparent}
.card.active .body::-webkit-scrollbar-thumb{background:var(--hairline);border-radius:5px}
.card.active .body:focus-visible{outline:2px solid var(--crimson);outline-offset:2px}

/* THE AFFORDANCE. A scrollbar alone is easy to miss on a short card and absent
   entirely on trackpad-overlay systems, so a fade sits over the last few lines
   whenever there is more below -- and is removed at the end, because a fade that
   never goes away is decoration that lies about there being more. `data-more`
   is set by JS from a real measurement, not assumed. */
.card.active .face{ position:relative }
.card.active .face[data-more="1"]::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:56px;
  background:linear-gradient(to bottom, transparent, var(--paper) 78%);
  pointer-events:none;border-radius:0 0 calc(var(--card-r) - 4px) calc(var(--card-r) - 4px);
}

.slot{ border-radius:var(--card-r);border:1px dashed var(--hairline);opacity:.55 }

/* The OTHER half of "the screen goes white". With a wash over the whole page
   AND the siblings at half opacity, the unlifted cards were washing out twice
   and all but disappearing. They only need to stop competing, not to vanish:
   drop their colour so the lifted card owns the only saturated strip on screen,
   and leave their substance alone. */
body.zoomed .card:not(.active){ filter:saturate(.25);opacity:.9;pointer-events:none }
/* THE BACKDROP TINTS NOTHING. It is a CLICK-CATCHER, and that is all it is.
   THREE versions were tried and the eye rejected all three, which is the whole
   lesson: the problem was never the COLOUR of the wash, it was that there was
   a wash.
     1. `backdrop-filter:blur(2px)` -- "all site goes out of focus".
     2. a dark wash, rgba(22,24,26,.40) -- "it goes dark".
     3. a paper wash, rgba(236,239,240,.78) -- "screen goes white".
   Every one of those repaints the ENTIRE viewport, including the rail, the
   headings and the section frame, to say one thing: this card is in front. The
   card can say that by itself. It carries a lit ARGB border and a 90px shadow,
   it is centred, it is huge, and it has a close button. So the scrim keeps the
   two jobs only it can do -- swallow the click that dismisses, and block
   interaction with what is behind -- and paints nothing at all. */
.scrim{
  position:fixed;inset:0;background:transparent;
  opacity:0;pointer-events:none;transition:opacity .35s ease;z-index:50;
}
body.zoomed .scrim{ opacity:1;pointer-events:auto }

.close{
  position:absolute;top:14px;right:16px;z-index:2;
  border:1px solid var(--hairline);background:#fff;border-radius:4px;
  font-family:'Spline Sans Mono',monospace;font-size:12px;color:var(--ink-2);
  padding:5px 10px;cursor:pointer;display:none;
}
.card.active .close{ display:block }

/* MOTION OFF. The strip becomes a still gradient, which still reads as the
   design; the deck stops drifting; the lift stops travelling and simply
   appears. The page loses nothing it needs. Each host keeps its OWN
   reduced-motion rules for its own furniture; these three are the deck's. */
@media (prefers-reduced-motion:reduce){
  .card, .card.active{ animation:none }
  .card, .card.active{ transition:none }
  .scrim{ transition:none }
}
