/* ============================================================================
   FUN BUT FAIR — Design System
   ----------------------------------------------------------------------------
   The ONE canonical home for every visual rule on the marketing site.
   (Design Constitution, Article XVI: one class, one definition, here.)

   TWO LAYERS, BY ROLE (see docs/design-system.md):
     · "Tivoli at NOON" — the brand layer. Bright candy + Bagel Fat One shout.
        Lives on the homepage: .uhero (the unhinged Surreal-Silliness collage hero),
        .home-grid (the mismatched gallery), the brightened sky, the candy tokens.
        Loud + joyful on purpose.
     · "Tivoli at DUSK" — the conversion surface. Cream/green/gilt, Abril +
        Fraunces. PDP / studio / article. The chrome RECEDES so the pet art is
        the star, and the green handpainted badge carries the Article IX claim.

   THE ONE MOVE (Dusk — the system Noon evolves from)
   Fun But Fair is a gallery midway. A hall of framed attractions — your pet
   the star of each idiom — on one calm cream wall, with the hand-painted
   commission as the headline tent. The FRAME is constant; the ART is the
   variety show (comic, watercolour, royal oil). The chrome recedes so a
   bright comic and a dark oil can hang side by side without either breaking.

   THE FIVE TYPES
     Attraction — one portrait (has a Style + a Tier). The only loud thing.
     Style      — the render idiom (House Ink, The Royal, Watercolour…).
     Bill       — hubs / listings (dogs, cats, people, gifts, occasions).
     Ticket     — labels, prices, tier badges, CTAs.
     Patter     — editorial voice + SEO copy.

   COLOUR IS A MORAL POSITION (Article III)
     ink   on cream ≈ 13:1   — body + headings
     green on cream ≈  7.4:1 — headings, links, the handpainted badge
     muted on cream ≈  4.7:1 — secondary text only (a real dark, never opacity)
     gilt  on cream ≈  2.8:1 — ORNAMENT/RULES ONLY. never text.
     rose  on cream ≈  2.0:1 — FILL/ACCENT ONLY. never text.

   New tokens require both keepers (Hana + Captain). Agents use what's here.
   ========================================================================== */

/* ---- 1. TOKENS ---------------------------------------------------------- */
:root {
  /* Palette — Tivoli at Dusk */
  --c-bg:        #F4F6FB;  /* cool pale ground — recessed tiles read bright, not dingy */
  --c-mat:       #FFFFFF;  /* bright white — card/frame/panel surfaces (Noon: bright all through) */
  --c-ink:       #241F1C;  /* warm near-black — all body + heading text */
  --c-muted:     #6B6259;  /* secondary text (passes 4.5:1; NOT faded ink) */
  --c-green:     #1F5E4E;  /* showman green — the brand colour */
  --c-green-deep:#16463A;  /* hover / pressed */
  --c-gilt:      #B9892F;  /* brass — fillets, rules, ornament. NEVER text. */
  --c-rose:      #D98A8A;  /* candy floss — fills + accents, sparingly. */
  --c-hairline:  #DAD5C7;  /* warm hairline on cream */
  --c-sky:       #7FC6F7;  /* baby-blue — the top of the page's sky gradient (brightened for Noon) */

  /* Palette — Tivoli at Noon (the brand layer). The dopamine candy spread.
     Blessed by both keepers 2026-06-16 (Captain approved the systematic Noon mock,
     "this is the line"). Used on chrome HERE on purpose — the Noon one move is the
     loud, joyful gallery, not the receding Dusk frame. NEVER on body text (none of
     these clear 4.5:1 on white); they are FILLS, FRAMES, and DISPLAY type only. */
  --c-tomato:    #FF5147;  /* primary candy red — the first word */
  --c-sunshine:  #FFC42E;  /* candy yellow — display only (fails on white as text) */
  --c-bubblegum: #FF73A8;  /* candy pink */
  --c-grape:     #7B5BE0;  /* candy violet — passes 4.5:1, the one candy that may be text/price */
  --c-mint:      #1FB87E;  /* candy green — the CTA pill */
  --c-mint-deep: #178A5D;  /* the pill's hard drop-shadow / pressed */
  --c-cobalt:    #2F6BFF;  /* electric blue — the unhinged clash accent (blessed 2026-06-16) */

  /* Type families — by role */
  --f-display: 'Abril Fatface', Georgia, 'Times New Roman', serif; /* Dusk: the bill */
  --f-text:    'Fraunces', Georgia, 'Times New Roman', serif;      /* Dusk: the patter */
  --f-mega:    'Bagel Fat One', system-ui, sans-serif;            /* Noon: the shout */
  --f-ui:      'Space Grotesk', system-ui, sans-serif;            /* Noon: UI + cards */

  /* Type scale — FIVE sizes, named, no gradient (Article II, XIV) */
  --t-mega:    24vw;                          /* the Noon shout — viewport-scaled, hero only */
  --t-display: clamp(2.75rem, 6vw, 5rem);   /* 44–80px  masthead / hero */
  --t-title:   clamp(1.9rem, 3.5vw, 2.75rem); /* 30–44px  page H1 */
  --t-heading: 1.375rem;                    /* 22px     section H2 */
  --t-body:    1.0625rem;                    /* 17px     body, H3, everything */
  --t-label:   0.875rem;                     /* 14px     tracked uppercase */

  /* Spacing — 4pt baseline (Article IV) */
  --s-1: 0.5rem; --s-2: 1rem; --s-3: 1.5rem;
  --s-4: 2.5rem; --s-5: 4rem; --s-6: 6rem;

  /* Layout */
  --measure: 68ch;     /* reading measure for Patter */
  --page-max: 1120px;
  --frame: 1px;        /* hairline weight */
}

/* ---- 2. RESET + BASE ---------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  /* The sky: baby-blue at the top fading to white at the foot — bright and
     positive, readable the whole way down. Fixed, so every screen sits under
     the same sky rather than the gradient stretching with the page. */
  background: linear-gradient(to top, #FFFFFF 0%, var(--c-sky) 100%) fixed;
  min-height: 100vh;
  color: var(--c-ink);
  font-family: var(--f-text);
  font-size: var(--t-body);
  line-height: 1.6;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, picture { max-width: 100%; display: block; }
a { color: var(--c-green); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--c-green-deep); }
:focus-visible { outline: 2px solid var(--c-green); outline-offset: 3px; border-radius: 1px; } /* Article X */
::selection { background: var(--c-rose); color: var(--c-ink); }
hr { border: 0; border-top: var(--frame) solid var(--c-hairline); margin: var(--s-4) 0; }

/* Voice split: Abril = the bill (h1, titles, names). Fraunces = the patter
   (everything you read, incl. section headings — a fat-face repeated in long
   copy reads heavy). */
h1 { font-family: var(--f-display); font-weight: 400; line-height: 1.1; margin: 0 0 var(--s-2); }
h2, h3 { font-family: var(--f-text); font-weight: 600; line-height: 1.2; margin: 0 0 var(--s-2); }
p { margin: 0 0 var(--s-2); }

/* ---- 3. TYPE ROLES (utilities + the markup's own class hooks) ---------- */
.t-display { font-family: var(--f-display); font-size: var(--t-display); line-height: 1.02; letter-spacing: -0.01em; }
.t-title   { font-family: var(--f-display); font-size: var(--t-title); line-height: 1.06; }
.t-heading { font-family: var(--f-text); font-weight: 600; font-size: var(--t-heading); }
.t-body    { font-family: var(--f-text); font-size: var(--t-body); }
.t-label   { font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
             text-transform: uppercase; letter-spacing: 0.14em; }

/* H3 = body SIZE in the display voice (a voice shift, not a 6th size) */
h3 { font-size: var(--t-body); font-weight: 600; letter-spacing: 0; }

/* ---- 4. PAGE SHELL ----------------------------------------------------- */
.page { max-width: var(--page-max); margin: 0 auto; padding: 0 var(--s-3) var(--s-6); }

/* ---- 5. THE BILL · top nav -------------------------------------------- */
.site-nav {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-3); flex-wrap: wrap;
  max-width: var(--page-max); margin: 0 auto;
  padding: var(--s-3); border-bottom: var(--frame) solid var(--c-hairline);
}
.site-nav__brand {
  font-family: var(--f-mega); font-size: 1.5rem; color: var(--c-ink);
  text-decoration: none; letter-spacing: 0;
}
.site-nav__brand:hover { color: var(--c-tomato); }
.site-nav__links { display: flex; gap: var(--s-3); margin: 0; padding: 0; list-style: none; }
.site-nav__links a {
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--c-ink); text-decoration: none;
}
.site-nav__links a:hover { color: var(--c-green); }

/* ---- 6. HERO · the masthead ------------------------------------------- */
.hero { max-width: var(--page-max); margin: 0 auto; padding: var(--s-6) var(--s-3) var(--s-5);
        text-align: center; }
.hero__eyebrow { /* the small showman line — restrained Painted Set */
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.22em; color: var(--c-green);
  margin: 0 0 var(--s-3);
}
.hero__title { font-size: var(--t-display); line-height: 1.02; letter-spacing: -0.01em;
               max-width: 16ch; margin: 0 auto var(--s-3); }
.hero__sub { font-size: 1.25rem; color: var(--c-muted); max-width: 48ch; margin: 0 auto; }
.rule-gilt { width: 64px; height: 0; border-top: 2px solid var(--c-gilt);
             margin: var(--s-4) auto; } /* the one ornament, used sparingly */

/* ---- 6b. UNHINGED HERO · the brand shout (Surreal Silliness) ----------- */
/* The full unhinged direction (docs/design-system.md): the mega wordmark shares
   space with collaged charming-bad pet portraits, on solid candy colour-blocks,
   with sticker badges + hand-drawn scribbles. Loud + joyful, "off its leash".
   DESKTOP = absolute collage. MOBILE (<760px) = the hero portrait FLOWS in the
   column so it never free-floats off a phone; the scatter becomes corner accents.
   The buying flow below stays legible on purpose — unhinged sells, doesn't dazzle. */
.uhero {
  position: relative; width: 100vw; margin-inline: calc(50% - 50vw);
  min-height: clamp(600px, 94vh, 920px);
  padding: var(--s-2) clamp(16px, 4vw, 40px) var(--s-5);
  overflow: hidden;
}
/* solid colour BLOCKS — tilted squircles, not white cards with coloured edges */
.uhero__block { position: absolute; border-radius: 42px; z-index: 1; }
.uhero__block--sun    { width: 46vw; height: 46vw; max-width: 620px; max-height: 620px;
  background: var(--c-sunshine); top: 13vh; left: 50%; transform: translateX(-54%) rotate(-8deg); }
.uhero__block--cobalt { width: 23vw; height: 23vw; max-width: 300px; max-height: 300px;
  background: var(--c-cobalt); top: 54vh; left: 9vw; transform: rotate(9deg); }
.uhero__block--grape  { width: 16vw; height: 16vw; max-width: 210px; max-height: 210px;
  background: var(--c-grape); top: 9vh; right: 6vw; transform: rotate(-12deg); }

/* collaged pet portraits (nano-banana, the FBF house style) */
.uhero__pic { position: absolute; border-radius: 36px; object-fit: cover; border: 6px solid #fff;
  box-shadow: 0 16px 0 -4px rgba(36, 31, 28, 0.12); z-index: 3; }
.uhero__pic--hero { width: 30vw; height: 36vw; max-width: 380px; max-height: 460px;
  top: 16vh; left: 50%; transform: translateX(-50%) rotate(3deg); z-index: 6; }
.uhero__pic--a { width: 16vw; height: 16vw; max-width: 210px; max-height: 210px; top: 60vh; left: 13vw; transform: rotate(-7deg); }
.uhero__pic--b { width: 14vw; height: 18vw; max-width: 180px; max-height: 230px; top: 12vh; right: 8vw; transform: rotate(8deg); }
.uhero__pic--c { width: 13vw; height: 13vw; max-width: 170px; max-height: 170px; bottom: 6vh; right: 13vw; transform: rotate(-5deg); }

/* THE SHOUT — shares space with the portraits; black ink stroke on candy letters */
.uhero__mega { position: relative; z-index: 5; margin: 0; padding-top: 6vh; text-align: center;
  font-family: var(--f-mega); line-height: 0.74; pointer-events: none; }
.uhero__mega span { display: block; font-size: var(--t-mega); -webkit-text-stroke: 3px var(--c-ink); }
.uhero__mega .w1 { color: var(--c-tomato); transform: rotate(-2deg); }
.uhero__mega .w2 { color: #fff; margin-top: -2vw; }       /* white middle word sits behind the hero pic */
.uhero__mega .w3 { color: var(--c-bubblegum); transform: rotate(2deg); margin-top: -2vw; }

/* sticker badges — pinned at angles, hand-cut. Copy is honest (no authorship claim) */
.uhero__sticker { position: absolute; z-index: 8; font-family: var(--f-ui); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 0.5em 0.9em; border-radius: 999px;
  border: 3px solid var(--c-ink); box-shadow: 0 4px 0 var(--c-ink);
  font-size: clamp(12px, 1.3vw, 16px); white-space: nowrap; }
.uhero__sticker--1 { background: var(--c-mint); top: 21vh; left: 14vw; transform: rotate(-11deg); }
.uhero__sticker--2 { background: var(--c-sunshine); top: 50vh; right: 11vw; transform: rotate(9deg); font-size: clamp(15px, 1.8vw, 22px); }
.uhero__sticker--3 { background: var(--c-bubblegum); color: #fff; top: 74vh; left: 26vw; transform: rotate(6deg); }
.uhero__sticker--4 { background: var(--c-cobalt); color: #fff; top: 30vh; right: 20vw; transform: rotate(-7deg); }

/* hand-drawn scribbles — colour driven from CSS (governed), SVG carries geometry only */
.uhero__scrawl { position: absolute; z-index: 7; pointer-events: none; }
.uhero__scrawl--loop  { bottom: 13vh; left: 50%; transform: translateX(-50%); width: 240px; }
.uhero__scrawl--star1 { top: 15vh; left: 30vw; width: 54px; }
.uhero__scrawl--star2 { top: 64vh; right: 30vw; width: 40px; }
.uhero__scrawl--arrow { top: 40vh; left: 6vw; width: 120px; }
.uhero__scrawl path        { stroke: var(--c-ink); }
.uhero__scrawl--star1 path { fill: var(--c-sunshine); }
.uhero__scrawl--star2 path { fill: var(--c-tomato); }
.uhero__scrawl--loop path  { fill: none; stroke: var(--c-tomato); }
.uhero__scrawl--arrow path { fill: none; }

/* the pitch — the offer, kept readable under the chaos */
.uhero__pitch { position: relative; z-index: 9; max-width: 760px; margin: 2vh auto 0; text-align: center; }
.uhero__eyebrow { display: inline-block; font-family: var(--f-ui); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.18em; font-size: var(--t-label);
  background: var(--c-ink); color: #fff; padding: 0.5em 0.9em; transform: rotate(-1.5deg); }
.uhero__lede { font-family: var(--f-ui); font-weight: 600; font-size: clamp(1.125rem, 2.4vw, 1.75rem);
  margin: var(--s-3) 0 0; color: var(--c-ink); }
.uhero__cta {                  /* mint pill, ink text + ink outline + hard shadow (passes ~7:1) */
  display: inline-block; margin-top: var(--s-3); font-family: var(--f-ui); font-weight: 700;
  font-size: 1.1875rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--c-ink); background: var(--c-mint); padding: 0.75em 1.7em; border-radius: 999px;
  text-decoration: none; border: 3px solid var(--c-ink); box-shadow: 0 6px 0 var(--c-ink);
  transform: rotate(-1deg); transition: transform 0.12s ease, box-shadow 0.12s ease; }
.uhero__cta:hover { transform: rotate(-1deg) translateY(2px); box-shadow: 0 4px 0 var(--c-ink); color: var(--c-ink); }

/* MOBILE — the hero portrait joins the flow; the scatter becomes light accents */
@media (max-width: 760px) {
  .uhero { min-height: auto; padding-bottom: var(--s-4); }
  .uhero__mega { padding-top: 2vh; }
  .uhero__pic--hero {                 /* now flows under the shout, slightly tilted */
    position: static; display: block; width: min(70vw, 320px); height: auto; aspect-ratio: 4 / 5;
    margin: -4vw auto var(--s-2); transform: rotate(-2deg); }
  .uhero__pic--a { width: 26vw; height: 26vw; top: 9vh; left: 3vw; bottom: auto; }
  .uhero__pic--b { width: 24vw; height: 28vw; top: 7vh; right: 3vw; }
  .uhero__pic--c { display: none; }
  .uhero__block--sun { top: 16vh; width: 70vw; height: 70vw; }
  .uhero__block--cobalt { width: 34vw; height: 34vw; top: auto; bottom: 24vh; left: 4vw; }
  .uhero__block--grape { width: 26vw; height: 26vw; top: 5vh; right: 2vw; }
  .uhero__sticker--1 { top: 16vh; left: 2vw; }
  .uhero__sticker--3, .uhero__sticker--4 { display: none; }   /* keep two stickers, not four */
  .uhero__sticker--2 { position: static; display: inline-block; margin: var(--s-2) auto 0; transform: rotate(-3deg); }
  .uhero__scrawl--arrow, .uhero__scrawl--star2 { display: none; }
  .uhero__pitch { margin-top: var(--s-3); }
}

/* ---- 7. THE ATTRACTION · framed portrait (the signature unit) ---------- */
/* A museum mat + a gilt fillet around the art. Constant frame, any idiom. */
.attraction { background: var(--c-mat); padding: clamp(10px, 2.4%, 18px);
              border: var(--frame) solid var(--c-hairline); }
.attraction__art {
  border: var(--frame) solid var(--c-gilt);   /* the gilt fillet */
  background: var(--c-mat); overflow: hidden;
  aspect-ratio: 3 / 4;                          /* portrait bill */
}
.attraction__art img { width: 100%; height: 100%; object-fit: cover; }
.attraction__caption { display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s-1) var(--s-2); margin-top: var(--s-2); }
.attraction__name { font-family: var(--f-display); font-size: var(--t-body); }

/* ---- 8. THE STYLE · idiom tag ----------------------------------------- */
.style-tag { font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--c-green); }

/* ---- 9. THE TICKET · price + tier badge ------------------------------- */
/* ----------------------------------------------------------------------- */
/* ARTICLE IX — DATA INTEGRITY, NON-NEGOTIABLE                             */
/*  .ticket--handpainted is a CLAIM ("a real artist painted a physical     */
/*  object"). Apply it ONLY to the genuine commission tier. NEVER on an     */
/*  AI preview or a print — even one rendered to look like oil paint.       */
/* ----------------------------------------------------------------------- */
.ticket { display: inline-flex; align-items: center; gap: 0.4em;
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.06em; padding: 0.3em 0.7em; white-space: nowrap; }
.ticket--instant {           /* general admission — printed merch / preview */
  color: var(--c-ink); border: var(--frame) solid var(--c-gilt); background: transparent; }
.ticket--handpainted {       /* the headline tent — REAL artist, physical */
  color: var(--c-mat); background: var(--c-green); border: var(--frame) solid var(--c-green); }
.ticket--handpainted::before { content: "✶"; color: var(--c-gilt); } /* gilt star */
.price { font-family: var(--f-display); font-size: var(--t-body); color: var(--c-ink); }

/* ---- 10. HOME GRID · the midway of attractions ------------------------- */
.home-grid__title {           /* the gallery's shout — mega face, grape (passes 4.5:1 as text) */
  font-family: var(--f-mega); font-size: clamp(2rem, 7vw, 5rem);
  color: var(--c-grape); line-height: 0.9; margin: var(--s-5) 0 var(--s-4);
}
.home-grid { display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
/* Noon: each card is a framed attraction on the bright midway. The frames are
   mismatched ON PURPOSE — the colour cycles by position (Etsy "Everyday Exhibits"
   gallery wall, +110%). One bright frame each, never a tasteful matched set. */
.home-grid__card {
  display: flex; flex-direction: column; gap: var(--s-2);
  background: #fff; padding: var(--s-2);
  border: 5px solid var(--c-tomato); border-radius: 10px;
  text-decoration: none; color: var(--c-ink);
  box-shadow: 0 8px 0 -1px rgba(35, 30, 27, 0.06);
  transition: transform 0.15s ease, box-shadow 0.15s ease; /* motion = informational */
}
.home-grid__card:nth-child(4n+2) { border-color: var(--c-sky); }
.home-grid__card:nth-child(4n+3) { border-color: var(--c-sunshine); }
.home-grid__card:nth-child(4n+4) { border-color: var(--c-bubblegum); }
.home-grid__card:hover { transform: translateY(-3px); box-shadow: 0 11px 0 -1px rgba(35, 30, 27, 0.06); }
.home-grid__name { font-family: var(--f-ui); font-weight: 600; font-size: var(--t-body); line-height: 1.2; }
.home-grid__price { font-family: var(--f-ui); font-size: var(--t-label); font-weight: 600;
  color: var(--c-grape); text-transform: uppercase; letter-spacing: 0.06em; }

/* ---- 11. ARTICLE · the Patter ----------------------------------------- */
.breadcrumb { max-width: var(--page-max); margin: 0 auto; padding: var(--s-3) var(--s-3) 0;
  font-family: var(--f-text); font-size: var(--t-label); color: var(--c-muted); }
.breadcrumb a { color: var(--c-green); text-decoration: none; }
.breadcrumb span { margin: 0 0.5em; }
.article { max-width: var(--measure); margin: 0 auto; }
.article__title { font-size: var(--t-title); line-height: 1.06; margin: var(--s-4) 0 var(--s-3); }
.article__body { font-size: var(--t-body); }
.article__body h2 { font-size: var(--t-heading); margin: var(--s-5) 0 var(--s-2); }
.article__body h3 { margin: var(--s-3) 0 var(--s-1); }
.article__body ul { padding-left: 1.2em; }
.article__body li { margin-bottom: var(--s-1); }

/* ---- 12. ITEM LIST + FAQ ---------------------------------------------- */
.item-list, .faq { max-width: var(--measure); margin: var(--s-5) auto 0; }
.item-list h2, .faq h2 { font-size: var(--t-heading); margin-bottom: var(--s-3); }
.item-list__item, .faq__item { padding: var(--s-3) 0; border-top: var(--frame) solid var(--c-hairline); }
.item-list__price { font-family: var(--f-display); color: var(--c-ink); }
.faq__q { font-size: var(--t-body); margin-bottom: var(--s-1); }
.faq__a { color: var(--c-ink); margin: 0; }

/* ---- 13. CTA ----------------------------------------------------------- */
.cta { max-width: var(--measure); margin: var(--s-6) auto 0; text-align: center; }
.cta__button {                 /* the candy pill — ink on mint passes ~7:1 (white would fail) */
  display: inline-block; font-family: var(--f-ui); font-size: var(--t-label); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--c-ink); background: var(--c-mint); text-decoration: none;
  padding: 0.85em 1.8em; border: none; border-radius: 999px; cursor: pointer;
  box-shadow: 0 5px 0 var(--c-mint-deep);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cta__button:hover { color: var(--c-ink); transform: translateY(2px); box-shadow: 0 3px 0 var(--c-mint-deep); }
.cta__button:disabled { background: var(--c-hairline); color: var(--c-muted);
  box-shadow: none; transform: none; cursor: not-allowed; } /* muted (a real dark), never opacity-faded */
/* Ghost = the quiet secondary / back button: a mint outline that fills on press.
   Modifier on existing tokens — no new token. */
.cta__button--ghost { background: transparent; color: var(--c-ink); box-shadow: inset 0 0 0 2px var(--c-mint); }
.cta__button--ghost:hover { background: var(--c-mint); color: var(--c-ink); transform: translateY(2px);
  box-shadow: 0 3px 0 var(--c-mint-deep); }
.cta__button--ghost:disabled { background: transparent; color: var(--c-muted);
  box-shadow: inset 0 0 0 2px var(--c-hairline); transform: none; }

/* ---- 14. EMPTY STATE (Article VIII — designed first, not an error) ----- */
.empty { max-width: var(--measure); margin: var(--s-6) auto; text-align: center;
  padding: var(--s-5); border: var(--frame) dashed var(--c-hairline); }
.empty__title { font-family: var(--f-display); font-size: var(--t-heading); margin-bottom: var(--s-1); }
.empty__body { color: var(--c-muted); margin: 0; }

/* ---- 15. FOOTER -------------------------------------------------------- */
.site-footer { max-width: var(--page-max); margin: var(--s-6) auto 0; padding: var(--s-5) var(--s-3);
  border-top: var(--frame) solid var(--c-hairline); text-align: center; }
.site-footer__brand { font-family: var(--f-display); font-size: 1.5rem; margin: 0 0 var(--s-1); }
.site-footer__tagline { color: var(--c-muted); margin: 0 0 var(--s-3); }
.site-footer__links { display: flex; gap: var(--s-3); justify-content: center; flex-wrap: wrap;
  margin: 0; padding: 0; list-style: none; }
.site-footer__links a { font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--c-ink); text-decoration: none; }
.site-footer__links a:hover { color: var(--c-green); }

/* ---- 16. SHOP · catalog grid + framed product cards ------------------- */
/* Each product is an Attraction hung on the wall: the constant mat+gilt frame,
   the art (the merch shot) the variety. Reuses the .attraction frame language
   and the .home-grid__card lift. Mobile-first: 2-up (the conversion surface). */
.shop__head { text-align: center; margin: var(--s-5) 0 var(--s-4); }
.shop__title { font-family: var(--f-display); font-size: var(--t-title); line-height: 1.06; }

.product-grid {
  display: grid; gap: var(--s-2);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 560px) { .product-grid { grid-template-columns: repeat(3, 1fr); gap: var(--s-3); } }
@media (min-width: 860px) { .product-grid { grid-template-columns: repeat(4, 1fr); } }
.product-grid__empty {
  grid-column: 1 / -1; text-align: center; color: var(--c-muted);
  padding: var(--s-5); border: var(--frame) dashed var(--c-hairline);
}

.product-card {                        /* same candy gallery frame as the homepage cards */
  display: flex; flex-direction: column; gap: var(--s-2);
  background: #fff; padding: var(--s-2);
  border: 5px solid var(--c-tomato); border-radius: 10px;
  text-decoration: none; color: var(--c-ink);
  box-shadow: 0 8px 0 -1px rgba(35, 30, 27, 0.06);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.product-card:nth-child(4n+2) { border-color: var(--c-sky); }
.product-card:nth-child(4n+3) { border-color: var(--c-sunshine); }
.product-card:nth-child(4n+4) { border-color: var(--c-bubblegum); }
.product-card:hover { transform: translateY(-3px); box-shadow: 0 11px 0 -1px rgba(35, 30, 27, 0.06); }
.product-card__image {                 /* the merch shot — a soft inner frame, the candy is the card */
  width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover;
  border: var(--frame) solid var(--c-hairline); border-radius: 6px; background: #fff;
}
.product-card__image--placeholder { display: grid; place-items: center; }
.product-card__image--placeholder::after { content: "✶"; color: var(--c-bubblegum); font-size: var(--t-heading); }
.product-card__title { font-family: var(--f-ui); font-weight: 600; font-size: var(--t-body); line-height: 1.2; }
.product-card__price {                 /* the candy price tag (grape passes 4.5:1 as text) */
  font-family: var(--f-ui); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--c-grape);
}
.product-card__soldout {               /* a clear badge, never a fade (Article IX + no-dim) */
  align-self: flex-start;
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.06em; color: var(--c-ink);
  border: var(--frame) solid var(--c-gilt); padding: 0.2em 0.6em;
}

/* ---- 17. PRODUCT · the detail page ------------------------------------ */
/* Hero frame (the museum mat, like .attraction) beside the bill + ticket.
   Mobile-first: stacks; two columns once there's room. */
.product__layout { display: grid; gap: var(--s-4); margin-top: var(--s-4); }
@media (min-width: 720px) {
  .product__layout { grid-template-columns: 1fr 1fr; gap: var(--s-5); align-items: start; }
}
.product__media {                      /* the PDP hero — one strong candy frame */
  background: #fff; padding: clamp(10px, 2.4%, 18px);
  border: 6px solid var(--c-grape); border-radius: 12px;
  box-shadow: 0 10px 0 -1px rgba(35, 30, 27, 0.06);
}
.product__image {
  width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover;
  border: var(--frame) solid var(--c-hairline); border-radius: 6px; background: #fff;
}
.product__image--placeholder { display: grid; place-items: center; }
.product__image--placeholder::after { content: "✶"; color: var(--c-grape); font-size: var(--t-title); }

.product__title { font-size: var(--t-title); margin-bottom: var(--s-2); }
.product__price {                      /* the headline ticket — display voice, prominent */
  font-family: var(--f-display); font-size: var(--t-heading); color: var(--c-ink);
  margin: 0 0 var(--s-3);
}
.product__desc { font-size: var(--t-body); color: var(--c-ink); max-width: var(--measure); }

.product__options { margin-top: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }
.product__option { display: flex; flex-direction: column; gap: var(--s-1); }
.product__option-name {
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--c-muted);
}
.product__option-values { display: flex; flex-wrap: wrap; gap: var(--s-1); margin: 0; padding: 0; list-style: none; }
.product__option-value {               /* read-only chip — the general-admission ticket border */
  font-family: var(--f-text); font-size: var(--t-label); color: var(--c-ink);
  border: var(--frame) solid var(--c-hairline); padding: 0.3em 0.7em;
}
.product__soldout {
  display: inline-block; margin-top: var(--s-3);
  font-family: var(--f-text); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.06em; color: var(--c-ink);
  border: var(--frame) solid var(--c-gilt); padding: 0.3em 0.7em;
}
/* The house CTA, tuned for the info column: left-aligned, snug to the options. */
.product__info .cta { margin: var(--s-4) 0 0; max-width: none; text-align: left; }

/* ---- 18. STUDIO · the "Create yours" wizard (React island, PDP-inline) - */
/* The ticket booth. Mounts in the product info column; mobile-first (THE
   conversion surface). Composes the frame/ticket/type system. Step 3's preview
   reveal is the emotional peak — the AI portrait lands in a gilt fillet, framed
   like the commission it promises. */
.studio {                              /* the conversion booth — bright, a sky candy frame */
  margin-top: var(--s-4); padding: var(--s-3);
  background: #fff; border: 5px solid var(--c-sky); border-radius: 14px;
  box-shadow: 0 8px 0 -1px rgba(35, 30, 27, 0.06);
  display: flex; flex-direction: column; gap: var(--s-3);
}
/* progress rail — a row of candy segments: done=mint, here=tomato, todo=hairline */
.studio__rail { display: flex; gap: var(--s-1); margin: 0; padding: 0; list-style: none; }
.studio__rail-step { flex: 1; height: 4px; border-radius: 999px; background: var(--c-hairline); }
.studio__rail-step[data-state="done"]    { background: var(--c-mint); }
.studio__rail-step[data-state="current"] { background: var(--c-tomato); }

.studio__error { margin: 0; padding: var(--s-2) var(--s-3); color: var(--c-ink);
  border-left: 3px solid var(--c-rose); background: var(--c-bg); }

.studio__step { display: flex; flex-direction: column; gap: var(--s-3); }
.studio__heading { font-family: var(--f-display); font-size: var(--t-heading); margin: 0; }
.studio__hint { color: var(--c-muted); margin: 0; }

/* STYLE — a grid of selectable idiom tickets */
.studio__styles { display: grid; gap: var(--s-2); grid-template-columns: repeat(2, 1fr);
  margin: 0; padding: 0; list-style: none; }
@media (min-width: 560px) { .studio__styles { grid-template-columns: repeat(3, 1fr); } }
.studio__style { width: 100%; height: 100%; text-align: left; cursor: pointer; font: inherit;
  display: flex; flex-direction: column; gap: 0.2em; padding: var(--s-2);
  background: var(--c-bg); border: var(--frame) solid var(--c-hairline); color: var(--c-ink);
  transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.studio__style:hover { border-color: var(--c-grape); }
.studio__style[data-selected="true"] { border-color: var(--c-mint);
  box-shadow: inset 0 0 0 2px var(--c-mint); }
.studio__style-label { font-family: var(--f-text); font-weight: 600; font-size: var(--t-body); }
.studio__style-blurb { font-size: var(--t-label); color: var(--c-muted); }

/* UPLOAD */
.studio__file { display: flex; align-items: center; justify-content: center; gap: var(--s-1);
  padding: var(--s-4) var(--s-3); cursor: pointer; text-align: center; font-weight: 600;
  border: var(--frame) dashed var(--c-hairline); background: var(--c-bg);
  transition: border-color 0.15s ease; }
.studio__file:hover { border-color: var(--c-mint); }
.studio__file input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.studio__consent { display: flex; align-items: flex-start; gap: var(--s-1); cursor: pointer; }
.studio__consent input { margin-top: 0.25em; accent-color: var(--c-mint); }
.studio__turnstile { min-height: 65px; }

/* actions — Back (ghost) + primary, splitting the row */
.studio__actions { display: flex; gap: var(--s-2); margin-top: var(--s-1); }
.studio__actions .cta__button { flex: 1; text-align: center; }

/* PREVIEW — the reveal. A museum-mat frame; the portrait arrives in the gilt fillet. */
.studio__preview { background: #fff; padding: clamp(10px, 2.4%, 18px);
  border: 5px solid var(--c-bubblegum); border-radius: 12px; aspect-ratio: 3 / 4;
  display: grid; place-items: center; overflow: hidden; } /* the reveal — a celebratory candy frame */
.studio__preview-img { width: 100%; height: 100%; object-fit: cover;
  border: var(--frame) solid var(--c-hairline); border-radius: 4px;
  animation: studio-reveal 0.5s ease both; } /* "here it is" — informational motion */
@keyframes studio-reveal { from { opacity: 0; transform: scale(0.985); } to { opacity: 1; transform: none; } }
.studio__spinner { width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid var(--c-hairline); border-top-color: var(--c-mint);
  animation: studio-spin 0.8s linear infinite; }
@keyframes studio-spin { to { transform: rotate(360deg); } }

/* CONFIGURE — variant tickets */
.studio__variants { display: flex; flex-direction: column; gap: var(--s-1); margin: 0; padding: 0; list-style: none; }
.studio__variant { width: 100%; cursor: pointer; font: inherit; text-align: left;
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2);
  padding: var(--s-2); background: var(--c-bg); border: var(--frame) solid var(--c-hairline);
  color: var(--c-ink); transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.studio__variant:hover { border-color: var(--c-grape); }
.studio__variant[data-selected="true"] { border-color: var(--c-mint);
  box-shadow: inset 0 0 0 2px var(--c-mint); }
.studio__variant-title { font-family: var(--f-text); font-weight: 600; }
.studio__variant-price { font-family: var(--f-display); color: var(--c-ink); }

/* FINISH — two finish tickets: AI (instant, chosen) vs Hand-Painted (coming, framed) */
.studio__tiers { display: grid; gap: var(--s-2); }
@media (min-width: 560px) { .studio__tiers { grid-template-columns: 1fr 1fr; align-items: start; } }
.studio__tier { display: flex; flex-direction: column; gap: var(--s-1); position: relative;
  padding: var(--s-3); background: var(--c-bg); border: var(--frame) solid var(--c-hairline); }
.studio__tier[data-selected="true"] { border-color: var(--c-mint);
  box-shadow: inset 0 0 0 2px var(--c-mint); }
.studio__tier--soon { border-color: var(--c-grape); } /* the real commission — premium, coming */
.studio__tier-badge { align-self: flex-start; margin-bottom: var(--s-1);
  font-family: var(--f-ui); font-size: var(--t-label); font-weight: 600; letter-spacing: 0.06em;
  color: var(--c-ink); border: 2px solid var(--c-grape); border-radius: 999px; padding: 0.2em 0.6em; }
.studio__tier-name { font-family: var(--f-display); font-size: var(--t-heading); }
.studio__tier-desc { color: var(--c-muted); margin: 0; }
.studio__tier-price { font-family: var(--f-display); color: var(--c-ink); }

/* ---- 19. MOTION OFF (Article X / VI) ---------------------------------- */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* ---- 20. TRUST SECTIONS (Miss B baseline 2026-07-07 — HANA TO ELEVATE) --
   Structural baseline only so the shop/PDP aren't paper-thin. Tokens only; candy used as
   fills/display, never body text. Redesign freely — this is a canvas, not a decision. */
.shop__lede { max-width: var(--measure); margin: var(--s-2) auto 0; text-align: center;
  font-family: var(--f-text); font-size: var(--t-body); color: var(--c-ink); }

.value-props { max-width: var(--page-max); margin: var(--s-5) auto; padding: 0 var(--s-4); }
.value-props__list { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
@media (min-width: 720px) { .value-props__list { grid-template-columns: repeat(4, 1fr); } }
.value-props__item { display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--s-1); padding: var(--s-3); background: var(--c-sky); min-width: 0; }
.value-props__icon { font-size: var(--t-title); line-height: 1; }
.value-props__label { font-family: var(--f-ui); font-weight: 700; font-size: var(--t-body); color: var(--c-ink); }
.value-props__sub { font-family: var(--f-text); font-size: var(--t-label); color: var(--c-ink); }

.how { max-width: var(--page-max); margin: var(--s-6) auto; padding: 0 var(--s-4); text-align: center; }
.how__title { font-family: var(--f-display); font-size: var(--t-title); color: var(--c-ink); }
.how__lede { font-family: var(--f-text); font-size: var(--t-body); color: var(--c-ink); margin: var(--s-1) 0 var(--s-4); }
.how__steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr; gap: var(--s-4); }
@media (min-width: 720px) { .how__steps { grid-template-columns: repeat(3, 1fr); } }
.how__step { display: flex; flex-direction: column; align-items: center; gap: var(--s-1); min-width: 0; }
.how__num { font-family: var(--f-display); font-size: var(--t-display); color: var(--c-tomato); line-height: 1; }
.how__step-title { font-family: var(--f-ui); font-weight: 700; font-size: var(--t-body); color: var(--c-ink); margin: 0; }
.how__step-text { font-family: var(--f-text); font-size: var(--t-body); color: var(--c-ink); margin: 0; max-width: 32ch; }

.promise { max-width: var(--measure); margin: var(--s-5) auto; padding: 0 var(--s-4); }
.promise__text { font-family: var(--f-text); font-size: var(--t-body); color: var(--c-ink);
  padding: var(--s-3); border: var(--frame) solid var(--c-hairline); background: var(--c-mat); margin: 0; }
