/* ═══════════════════════════════════════════════════════════════════════════════════
   CARD TOKENS — THE TWO BASES
   ───────────────────────────────────────────────────────────────────────────────────
   CANONICAL FILE. This is the only place any of these values is typed. It is copied into
   consumers by each app's scripts/sync-card-chrome.mjs — editing a copy appears to work,
   because the app reloads and you can see the change, and is then silently reverted on the
   next predev/prebuild. Edit HERE.

   THE OWNER'S STANDARD, and the whole reason this file exists: one place to change a value.
   There are exactly two bases, because there are exactly two things a visitor opens.

     A) THE FULL CARD — what you get when you click a tile or a mark. --uc-card-*.
     B) THE SMALL INFO SURFACE — the little panel a card opens for one piece of information
        (About, links, a detail row). --uc-info-*.

   Anything unique to one surface is an OVERRIDE: it re-declares a token on its own element
   rather than writing a competing rule. That difference matters more than it looks. A
   competing rule has to out-specify the base — this project has been bitten by that five
   times in one stylesheet alone, because a variant at (0,2,0) loses to a base at (0,3,0) no
   matter how late it appears. A token re-declaration resolves on the element that reads it,
   so there is nothing to lose to.

   ── THE THREE THINGS THAT WILL BITE YOU ────────────────────────────────────────────
   1. EVERYTHING HERE IS DECLARED AT :root, ON PURPOSE, and geometry tokens must stay there.
      Custom properties inherit, and the two card topologies in this product are opposite:
      reality-details and contact-card render their <dialog> as a SIBLING of the card, while
      gamified-story-site nests it INSIDE the card. Declare --uc-card-w on a card element and
      the nested host's popup inherits 480 while the sibling hosts' popups stay 544 — one
      token, two widths, decided by markup nesting nobody inspects. That is why the popup
      reads a DIFFERENTLY NAMED token (--uc-pop-w) instead of sharing one.

   2. showModal() MOVES PAINT ORDER, NOT THE TREE. A dialog in the top layer escapes the
      card's overflow, radius, stacking context and transforms — so nothing on screen
      suggests it is still a descendant. It is, and it still inherits every custom property
      the card sets. ::backdrop inherits from the dialog, so scrim tokens declared here reach
      it in both topologies; a scrim token set anywhere between root and the dialog would
      reach it in only one.

   3. NEVER STOP A TOKEN WITH `initial`. On a custom property `initial` is the
      guaranteed-invalid value: every var() reading it falls back, or becomes invalid at
      computed-value time and silently computes to zero. That is the exact failure that once
      collapsed .info-section's padding to nothing. To stop a token, re-set it to a value.
   ═══════════════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── A) THE FULL CARD ──────────────────────────────────────────────────────────── */

  /* THE width the owner named first. 480 is what four surfaces already authored
     independently; the two 488s elsewhere are 480 plus 8px of outer padding, the same
     intent written differently. */
  --uc-card-w: 480px;

  --uc-card-radius: 16px;
  /* a hairline inset by 1px must curve 1px tighter or its corners cut the card's */
  --uc-card-radius-inner: calc(var(--uc-card-radius) - 1px);

  /* the COLOR is its own token, and the shorthand is built from it. A consumer that writes
     `border: 1px solid var(--…)` needs a colour, not "1px solid rgba(…)" — feed it the
     shorthand and the declaration is invalid and the border silently disappears. Both forms
     exist so neither consumer has to retype the value. */
  --uc-card-border-color: rgba(255,255,255,.105);
  --uc-card-border: 1px solid var(--uc-card-border-color);
  --uc-card-bg:
    linear-gradient(180deg, rgba(255,255,255,.042) 0%, rgba(26,31,27,.90) 18%, rgba(16,20,17,.92) 100%);
  /* the 30px accent bloom is the REFERENCE CARD'S — the gamified-story card carried it in its
     own --gsc-outer-shadow while this token did not, so the same card glowed on one page and
     not on another. It is MATERIAL, not a state: the same distinction storyCard.css already
     draws when it strips the tile's resting halo but keeps the frosted accent corner ("that is
     glass, not a state"). It reads --accent-rgb rather than a literal green, so a plugged
     reality's card blooms in the reality's own colour. */
  --uc-card-shadow:
    inset 0 1px 0 rgba(255,255,255,.10),
    inset 0 -1px 0 rgba(0,0,0,.38),
    0 0 30px rgba(var(--accent-rgb), .13),
    0 18px 54px rgba(0,0,0,.28);
  --uc-card-blur: 12px;
  /* the bright hairline a framed surface (tile art, plug stage) draws around itself */
  --uc-frame-border: rgba(255,255,255,.22);

  /* the glass, as two reusable layers rather than two more copies of the same gradients */
  --uc-sheen:
    radial-gradient(80% 54% at 18% 0%, rgba(255,255,255,.11), transparent 58%),
    radial-gradient(54% 42% at 92% 18%, rgba(255,255,255,.06), transparent 62%);
  --uc-hairline:
    inset 0 1px 0 rgba(255,255,255,.18),
    inset 0 0 0 1px rgba(255,255,255,.035);

  --uc-card-pad: 12px;
  --uc-card-ink: #e5e5e5;
  --uc-rule: rgba(255,255,255,.16);
  --uc-pill: 9999px;

  /* ── THE INK (owner 2026-08-01) ───────────────────────────────────────────────────
     THE PRODUCT'S ink is 229-based — every heading, every paragraph, the tab chips. The
     card's used to be 255-based (pure #fff titles, rgba(255,255,255,.9x) values), which is
     what this file shipped and what the mockups were drawn in, and side by side on one page
     the card read a half-step colder and brighter than everything around it. The owner
     previewed the 229 scale on one story and took it.
     It was then applied as a LOCAL override on that one card, so every other card kept the
     255 ink — which is how the Experience Card ended up with pure-white row labels. The
     decision belongs here, where it reaches all of them. */
  --uc-ink: #e5e5e5;
  --uc-ink-strong: rgba(229,229,229,.90);   /* values, body copy, a row's answer */
  --uc-ink-muted: rgba(229,229,229,.72);    /* labels — the question, not the answer */
  --uc-ink-quiet: rgba(229,229,229,.82);    /* chips and other secondary marks */

  /* ── THE CARD'S TITLE ─────────────────────────────────────────────────────────────
     One card wrote 24/1.15, the other 24/1.2 — the same heading with two line-heights,
     because each transcribed it separately from the same mockup. */
  --uc-title-size: 24px;
  --uc-title-lh: 1.15;
  --uc-title-weight: 800;
  --uc-title-tracking: -.02em;

  /* ── THE SHELF TILE ───────────────────────────────────────────────────────────────
     The minified card. Only its MEDIA differs between families (a story shows 3/2 art, an
     experience shows its plug stage) — the body, the name and the padding are one thing. */
  --uc-tile-pad: 14px 14px 16px;
  --uc-tile-name-size: 20px;
  --uc-tile-name-weight: 700;
  --uc-tile-name-tracking: -.01em;

  /* a section that holds DETAIL ROWS hugs them: the rows carry their own vertical rhythm,
     so the box does not add a second one. (A section holding prose uses --uc-info-pad.) */
  --uc-rows-pad: 6px 16px;
  --uc-rows-pad-sm: 4px 12px;

  /* ── THE REALITY CAPSULE'S SIZE ───────────────────────────────────────────────────
     Owner 2026-08-01: .46 on a tile made the identity "an afterthought" and the name landed
     under the tile's own smallest type, so the tile went ONE STEP UP to .62. That decision
     was applied to the story tile only — the Experience Card's tiles were still on the .46
     the owner had already rejected. */
  --uc-cap-tile: .62;
  --uc-cap-tile-sm: .54;
  --uc-cap-card: .66;
  --uc-cap-card-sm: .56;

  /* ── the POPUP the card opens ──────────────────────────────────────────────────── */
  /* separate from --uc-card-w deliberately: see trap 1 above */
  --uc-pop-w: 34rem;
  --uc-pop-gutter: 16px;
  --uc-scrim: rgba(0,0,0,.78);
  --uc-scrim-blur: 8px;

  /* ── B) THE SMALL INFO SURFACE ─────────────────────────────────────────────────── */
  /* These are the values .about-docs already used. The base underneath it declared a
     #101312 fill and a .10 border that were never once painted — every emission site pairs
     the two classes, so the override always won. The base now IS the values that ship. */
  --uc-info-bg: rgba(255,255,255,.07);
  --uc-info-border-color: rgba(255,255,255,.14);
  --uc-info-border: 1px solid var(--uc-info-border-color);
  --uc-info-radius: 16px;
  --uc-info-shadow: 0 12px 28px rgba(0,0,0,.12);
  --uc-info-pad: var(--uc-card-pad);
  --uc-info-sheen: var(--uc-sheen);

  /* ── THE TWO SHELLS a card opens in ────────────────────────────────────────────
     Consumed by .uc-sheet* and .uc-info-panel in card-chrome.css. Change a number here and
     every card on the platform moves — which is the entire point of them being here rather
     than typed into each app. */
  --uc-sheet-w: 676px;                 /* the scroll column the card sits in = card + 14px each side */
  --uc-sheet-card-w: min(648px, 80vw); /* the card inside it — the owner's number */
  --uc-sheet-pad: 24px 12px;
  --uc-sheet-scrim-bg: rgba(0,0,0,.65); /* card-chrome's own ::backdrop value — a card overlay
                                           and a card dialog dim the page by the same amount */
  --uc-sheet-scrim-blur: 4px;
  --uc-sheet-motion: 240ms;
  /* HIGH ON PURPOSE: the story site paints a click-ripple layer at 10100 and an image
     lightbox at 10200, and a sheet that opens under either is a sheet you cannot use. A host
     with nothing to clear is unaffected by the number being large. */
  --uc-sheet-z: 10300;

  --uc-info-panel-w: min(420px, 92vw);
  --uc-info-panel-pad: 20px;
  --uc-info-panel-bg: linear-gradient(180deg, rgba(26,31,27,.985) 0%, rgba(16,20,17,.99) 100%);
  --uc-info-scrim: rgba(0,0,0,.45);    /* LIGHT on purpose — you still see the card */
  --uc-info-scrim-blur: 2px;
  --uc-info-sheet-max: min(50svh, calc(100svh - 72px));  /* the phone bottom sheet */
  --uc-info-motion: 300ms;

  /* ── type ─────────────────────────────────────────────────────────────────────── */
  --uc-fd: "Poppins", system-ui, sans-serif;
  --uc-fb: "Inter", system-ui, sans-serif;

  /* ── the one theming hook ─────────────────────────────────────────────────────────
     A host that plugs a reality sets --accent / --accent-rgb on document.documentElement,
     which is the only place that reaches a top-layer dialog in BOTH topologies. These are
     the platform defaults for a host that sets nothing. */
  --accent: #38ff38;
  --accent-rgb: 56, 255, 56;
}

/* The card's padding steps up once there is room for it. Folded into the token rather than
   restated per surface, so one breakpoint exists instead of the several that had drifted. */
@media (min-width: 400px) {
  :root { --uc-card-pad: 20px; }
}
