/* ==========================================================================
   ParkSyde — the SHOP ENCLAVE dress. Loaded by shop pages rebuilt to the
   owner's brief of 12 August 2026: "reproduce the park inside the shop
   pages… large spread out with push buttons of content… replicate the depth
   and design of the park."

   This file loads AFTER life/park-clearing.css and rides its tokens
   (--gold, --paper, --serif …) and its shared furniture (#sky, #scene,
   #still, #enter-flash, .wm, .wayout, .btn, .facts, .urgent, .eyebrow,
   .lede, .body). It adds exactly three new things:

     1. .shop-mast     — the masthead: name, one-line lede, the price.
     2. .st-nav / .st  — the PUSH-BUTTON LABELS. Real anchors, projected
                          over the 3-D posts by life/park-shop.js. The world
                          itself stays wordless (charter rule 2): these are
                          DOM, never textures.
     3. .shop-card     — one topic's content, opened by its button.

   THREE STATES, ONE MARKUP — and the default state is the one with the
   least machinery, so failure always lands on the readable page:

     · NO JAVASCRIPT (no .js on <html>): the buttons are plain anchor links
       and the cards are plain sections stacked in flow below the still —
       look first (padding-top clears a screen for the picture), then read.
       Charter rule 14. Nothing here needs a script to be legible.
     · JS, NO WEBGL / REDUCED MOTION (html.js body.flat): the still shows;
       the buttons stand as a static column; a press opens its card as a
       sheet. The card machinery is DOM and needs no GPU.
     · JS + WEBGL (html.js, no .flat): buttons are positioned every frame
       over their posts in the world; a press walks the camera over and
       opens the card.
   ========================================================================== */

/* ---- the masthead -------------------------------------------------------
   Compact and top-left, under the wordmark: the shop's name, its one-line
   lede, and the price. The price line is a [data-park-fee] slot — charter
   rule 8, no typed price — and it stays in the masthead because the lede
   promises "you see the price before anything starts", and a promise like
   that may not itself be behind a button. Everything else is. */
.shop-mast{position:relative;z-index:5;pointer-events:none;
  padding:76px 24px 0;max-width:560px}
.shop-mast .eyebrow{margin:0 0 8px}
.shop-mast h1{font-family:var(--serif);font-weight:500;margin:0;
  font-size:clamp(1.9rem,5vw,2.7rem);line-height:1.05;letter-spacing:-.02em;
  text-shadow:0 2px 18px rgba(7,17,16,.85)}
.shop-mast .lede{font-size:clamp(1rem,2.1vw,1.2rem);margin:6px 0 0;
  text-shadow:0 1px 12px rgba(7,17,16,.85)}
.shop-mast .mast-cost{margin:10px 0 0;font-family:var(--mono);
  font-size:.86rem;color:var(--gold-soft);letter-spacing:.01em;
  text-shadow:0 1px 12px rgba(7,17,16,.9)}
@media (max-width:720px){
  .shop-mast{padding:70px 18px 0}
}

/* ---- the push-button labels ---------------------------------------------
   Default (JS off): a plain wrapped row of links under the masthead — a
   table of contents that anchors down to the stacked sections. Each is
   min-height 44px, STATED not computed (bite 13 in tools/CURATOR.md).   */
.st-nav{position:relative;z-index:5;display:flex;flex-wrap:wrap;gap:9px;
  padding:18px 24px 0;max-width:640px}
/* EACH SHOP WEARS ITS OWN ACCENT on the buttons too: a page sets
   --shop-accent / --shop-accent-soft on :root (home-school is green) and
   everything below follows. Unset, they fall back to the park's gold. */
.st{display:inline-flex;align-items:center;gap:8px;min-height:44px;
  padding:9px 16px;border-radius:999px;
  font-family:var(--sans);font-weight:600;font-size:.88rem;line-height:1.2;
  color:var(--paper);text-decoration:none;
  background:rgba(8,20,20,.78);border:1px solid var(--shop-accent-dim,rgba(228,169,60,.42));
  box-shadow:0 8px 26px rgba(0,0,0,.35)}
.st::before{content:"";flex:0 0 auto;width:9px;height:9px;border-radius:50%;
  background:var(--shop-accent,var(--gold));
  box-shadow:0 0 10px var(--shop-accent,rgba(228,169,60,.8))}
.st:hover,.st:focus-visible{border-color:var(--shop-accent-soft,var(--gold-soft));
  background:rgba(12,28,26,.9)}
.st:focus-visible{outline:2px solid var(--shop-accent,var(--gold));outline-offset:3px}
.st[aria-expanded="true"]{background:var(--shop-accent,var(--gold));color:#1c1403}
.st[aria-expanded="true"]::before{background:#1c1403;box-shadow:none}
/* while a card is open the other labels step back — still there, still
   tappable (a guest can walk straight from one button to the next), just
   not competing with the words being read */
html.js body.card-open:not(.flat) .st{opacity:.35}
html.js body.card-open:not(.flat) .st[aria-expanded="true"],
html.js body.card-open:not(.flat) .st:hover,
html.js body.card-open:not(.flat) .st:focus-visible{opacity:1}

/* JS + WebGL: every label leaves the flow and stands over its own post in
   the world, placed each frame by park-shop.js writing --sx/--sy. The
   translate(-50%,-100%) hangs the label just above the post's button dome.
   A label whose post is behind the camera gets [hidden].
   Labels stay tappable while a card is open — a guest can walk straight
   from one button to the next — but the open one reads pressed (above). */
html.js body:not(.flat) .st-nav{position:static;padding:0;max-width:none}
html.js body:not(.flat) .st{position:fixed;z-index:5;margin:0;
  left:var(--sx,-999px);top:var(--sy,-999px);
  transform:translate(-50%,-100%);
  white-space:nowrap;  /* a floating label is one line; wrapped it read as
                          two stacked buttons on the first phone build */
  transition:opacity .25s ease}
html.js body:not(.flat) .st[hidden]{display:none}
/* ---- ON A PHONE THE BUTTONS DO NOT FLOAT AT ALL -------------------------
   13 August 2026, after the owner's iPhone twice reported "the buttons
   don't work": a label repositioned every frame is a tap target that can
   move out from under a finger, and no amount of freezing fully closes
   that class of bug on iOS. So on any coarse-pointer device the labels
   never leave the flow of a DOCKED ROW — fixed above the crisis pill's
   band, wrapping to two lines when they must, never moved by a script.
   The room plays behind them; a press still walks the camera over and
   opens the card; the only thing lost is the floating label, which was
   the one part a phone could not reliably touch. life/park-shop.js skips
   its per-frame projection under the same media query, so the two halves
   cannot disagree. */
@media (pointer:coarse){
  /* the dock stands ABOVE the crisis pill's whole band (.ps-help--clearing
     bottom 132px + its 38px summary = 170px), measured after a tap on the
     first build's row landed on the pill instead of the button under it —
     which was, at last, the owner's "the buttons don't work", reproduced */
  html.js body:not(.flat) .st-nav{position:fixed;left:10px;right:10px;
    bottom:calc(180px + env(safe-area-inset-bottom,0px));z-index:5;
    display:flex;flex-wrap:wrap;gap:7px;justify-content:center;
    padding:0;pointer-events:none}
  html.js body:not(.flat) .st{position:static;transform:none;margin:0;
    pointer-events:auto;white-space:nowrap;font-size:.8rem;padding:8px 13px}
  html.js body:not(.flat) .st[hidden]{display:inline-flex}
}

/* JS, no WebGL (or reduced motion): body.flat — the still shows and the
   buttons hold their in-flow column. Nothing else to do: the default
   layout above IS this state. */

/* ---- the cards -----------------------------------------------------------
   Default (JS off): plain sections in flow inside <main class="shop">,
   stacked below a full screen of the picture. The .panel dress from
   park-clearing.css carries the readable dark ground — measured there
   against the scene's own whites; see THE WASH note in that file.        */
main.shop{position:relative;z-index:5;
  /* look first, then read: the picture gets the first screen (the same
     device the whole park is measured on), the words start under it */
  padding:88vh 20px 120px;padding-top:88svh;
  display:flex;flex-direction:column;gap:18px;align-items:flex-start}
.shop-card{max-width:min(560px,92vw);
  /* the .panel ground from park-clearing.css, carried by every state of a
     card: stacked in flow with scripts off, and opened as a sheet with
     them on. .86 is measured, not taste — see THE WASH in that file. */
  background:rgba(8,20,20,.86);border:1px solid rgba(228,169,60,.22);
  border-radius:18px;padding:20px 18px 18px;
  box-shadow:0 30px 80px rgba(0,0,0,.4);backdrop-filter:blur(7px)}
.shop-card h2{font-family:var(--serif);font-weight:500;margin:0 0 4px;
  font-size:1.35rem;letter-spacing:-.01em}
.shop-card .card-close{display:none}

/* JS on: the cards leave the flow and wait, closed, behind their buttons.
   main.shop stops reserving a reading column — the world has the page. */
html.js main.shop{display:block;padding:0}
html.js .shop-card{display:none}
html.js .shop-card.open{display:block;position:fixed;z-index:8;
  left:12px;right:12px;bottom:12px;max-width:none;max-height:72vh;max-height:72svh;
  overflow-y:auto;overscroll-behavior:contain;
  background:rgba(8,20,20,.92);border-color:rgba(228,169,60,.3);
  box-shadow:0 30px 80px rgba(0,0,0,.55)}
@media (min-width:821px){
  html.js .shop-card.open{left:auto;right:28px;bottom:28px;width:420px}
}
/* the close control: drawn, wordless by house style, never nameless
   (aria-label in the markup), and 44px STATED. First in the card's DOM so
   it is the first Tab stop inside an opened card and Escape's visible twin. */
html.js .shop-card .card-close{display:inline-flex;align-items:center;justify-content:center;
  position:sticky;top:0;float:right;width:44px;height:44px;min-height:44px;
  margin:-6px -4px 0 10px;border:1px solid rgba(237,231,218,.3);border-radius:50%;
  background:rgba(8,20,20,.9);color:var(--paper);cursor:pointer;font-size:0}
html.js .shop-card .card-close svg{width:16px;height:16px;stroke:currentColor;
  stroke-width:2;fill:none;stroke-linecap:round}
html.js .shop-card .card-close:hover{border-color:var(--gold-soft)}
html.js .shop-card .card-close:focus-visible{outline:2px solid var(--gold);outline-offset:2px}

/* the card grows out of its button's press — kept to opacity+rise so it
   costs nothing to a guest who prefers reduced motion (guarded below) */
@media (prefers-reduced-motion:no-preference){
  html.js .shop-card.open{animation:cardUp .3s ease-out both}
  @keyframes cardUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
}

/* ---- odds and ends -------------------------------------------------------
   The backline pins itself to the viewport bottom in park-clearing.css on a
   desktop but goes back into the flow on a phone (its own 720px rule). With
   JS on this page has almost no flow, so the phone rule would beach it just
   under the masthead — pin it back down in every JS state. With JS off the
   park-clearing.css rules stand untouched. */
html.js .backline{position:fixed;left:0;right:0;bottom:14px;margin:0;text-align:center}
