/* Puck editor chrome — BackGold skin.
   Puck themes exclusively through the --puck-* custom properties it defines at
   :root (@puckeditor/core dist/index.css); redefining them on the mount div
   re-skins every descendant without touching Puck internals, and wins over the
   :root defaults regardless of stylesheet load order. We keep Puck's remapping
   approach but SOURCE every value from our theme tokens (--ink, --surface,
   --gold-*) instead of hard-coded parchment/brass hex, so the builder chrome
   follows light/dark automatically. The azure scale (Puck's action color)
   becomes a brass/gold ramp blended between --gold-ink and --gold-1; the neutral
   grey scale is blended between --ink and --surface. Each color-mix percentage
   is picked to reproduce the original step's lightness in the light theme, which
   means the ramps invert correctly in the dark theme (where --ink is cream and
   --surface is espresso) — so Puck's contrast pairings (white-on-azure buttons,
   ink-on-paper text) keep working in both themes. The React island's custom
   fields reference these same vars inline. */
.gg-puck-builder {
  --puck-color-white: var(--surface);
  --puck-color-black: var(--ink);

  /* Action ramp — brass/gold. Low steps blend --gold-ink→--gold-1 (kept dark so
     white button text stays legible); high steps blend --gold-1→--surface. */
  --puck-color-azure-01: color-mix(in srgb, var(--gold-1) 17%, var(--gold-ink));
  --puck-color-azure-02: color-mix(in srgb, var(--gold-1) 29%, var(--gold-ink));
  --puck-color-azure-03: color-mix(in srgb, var(--gold-1) 40%, var(--gold-ink));
  --puck-color-azure-04: color-mix(in srgb, var(--gold-1) 49%, var(--gold-ink));
  --puck-color-azure-05: color-mix(in srgb, var(--gold-1) 65%, var(--gold-ink));
  --puck-color-azure-06: color-mix(in srgb, var(--gold-1) 80%, var(--gold-ink));
  --puck-color-azure-07: var(--gold-1);
  --puck-color-azure-08: color-mix(in srgb, var(--gold-1) 92%, var(--surface));
  --puck-color-azure-09: color-mix(in srgb, var(--gold-1) 58%, var(--surface));
  --puck-color-azure-10: color-mix(in srgb, var(--gold-1) 33%, var(--surface));
  --puck-color-azure-11: color-mix(in srgb, var(--gold-1) 17%, var(--surface));
  --puck-color-azure-12: color-mix(in srgb, var(--gold-1) 8%, var(--surface));

  /* Neutral ramp — 01 = strongest ink, 12 = subtlest paper. Blends --ink→
     --surface; inverts automatically in dark (ink = cream, surface = espresso). */
  --puck-color-grey-01: var(--ink);
  --puck-color-grey-02: color-mix(in srgb, var(--ink) 90%, var(--surface));
  --puck-color-grey-03: color-mix(in srgb, var(--ink) 78%, var(--surface));
  --puck-color-grey-04: color-mix(in srgb, var(--ink) 66%, var(--surface));
  --puck-color-grey-05: color-mix(in srgb, var(--ink) 54%, var(--surface));
  --puck-color-grey-06: color-mix(in srgb, var(--ink) 42%, var(--surface));
  --puck-color-grey-07: color-mix(in srgb, var(--ink) 32%, var(--surface));
  --puck-color-grey-08: color-mix(in srgb, var(--ink) 23%, var(--surface));
  --puck-color-grey-09: color-mix(in srgb, var(--ink) 13%, var(--surface));
  --puck-color-grey-10: color-mix(in srgb, var(--ink) 7%, var(--surface));
  --puck-color-grey-11: color-mix(in srgb, var(--ink) 4%, var(--surface));
  --puck-color-grey-12: color-mix(in srgb, var(--ink) 2%, var(--surface));
}

/* §55 in-place builder layout (app/react/builder/editor.tsx).
   The mount div is .gg-puck-builder (still the --puck-* skin source above); the
   custom composition replaces Puck's three-panel UI with its own frame: top
   bar, page rail, then a body of ONE side panel (left — the selected module's
   options, or the site settings) beside a parchment canvas holding a centered
   page card that reads like the published site. The top bar, rail, panel and
   the floating per-module action bar are styled inline in the React island
   against the same --puck-* vars, and the in-canvas selection outline is
   skinned inside the iframe (applyThemeToCanvas), so nothing here fights the
   re-skin. */
.gg-bx-editor {
  background: var(--surface-2);
}

/* The body row: side panel + canvas share the height left under the bars. */
.gg-bx-body {
  flex: 1;
  min-height: 0;
  display: flex;
}

/* The side panel scrolls on its own so a long module form never scrolls the
   canvas away. No padding of its own: Puck's fields form brings a 16px inset,
   and the panel's header + site-settings blocks pad themselves to match. */
.gg-bx-side {
  flex: 0 0 320px;
  min-height: 0;
  overflow-y: auto;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.gg-bx-side-head {
  padding: 12px 16px 0;
}

.gg-bx-side-settings {
  padding: 12px 16px 16px;
}

.gg-bx-canvas {
  flex: 1;
  min-height: 0;
  display: flex;
  justify-content: center;
  padding: 16px 14px;
  background: var(--surface-2);
}

/* The page card fills the canvas height (cross-axis stretch) so Puck.Preview's
   height:100% iframe resolves and the page scrolls inside it; it grows toward
   the ~1120px reading width and shrinks on narrow screens.

   The card must NOT clip (no overflow: hidden): the nav strip's per-item manage
   popovers are position:absolute inside it, and clipping cut them off at the
   card edge — unusable on any pill near the right, which is exactly where the
   header button always sits. The rounded corners are kept by rounding the
   children instead: the first child (the nav strip, or the preview when the
   page has no site nav) takes the top corners, the last child (the preview
   wrapper) takes the bottom ones and clips the iframe itself. */
.gg-bx-page {
  flex: 1 1 1120px;
  max-width: 1120px;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 11px;
  box-shadow: var(--shadow);
}

.gg-bx-page > :first-child {
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
}

.gg-bx-page > :last-child {
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
  overflow: hidden;
}

/* Landing-page template gallery (Phase 3.5). Plain global rules so the picker
   stays out of the lazy Puck/React island; classes are gg-tp-* namespaced.
   Sourced from theme tokens so the gallery follows light/dark. */
.gg-template-picker {
  max-width: 1120px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.gg-tp-head {
  margin-bottom: 24px;
}

.gg-tp-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 4px;
}

.gg-tp-sub {
  font-size: 15px;
  color: var(--muted);
  margin: 0;
}

.gg-tp-section-title {
  font-size: 17px;
  font-weight: 700;
  color: var(--ink);
  margin: 32px 0 12px;
}

.gg-tp-section-title + .gg-tp-sub {
  margin: -8px 0 12px;
}

.gg-tp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}

/* TEMPLATE-CARD THUMBNAIL (#475) — ONE mechanic for every template gallery:
   the create-a-site gallery, the add-a-page gallery, the landing-template
   picker, and the in-editor quick-add popover. Do not fork it; a card that
   scales differently from its neighbours is the bug this rule replaced.

   The old rule framed a 4x-wide iframe scaled 1/4 into a 128px-tall strip, so
   every card showed the top ~500px of the page and nothing else — the whole
   catalog previewed as "headline + Donate button", which is why differentiated
   seeds still read as clones. This shows a TALL view instead: the iframe's
   viewport is 5x the card box in BOTH axes and is scaled by exactly 1/5, so it
   fills the card edge-to-edge (no letterbox, no white gutter under a dark
   template) at whatever width the grid hands the card. With the 4/5 card
   aspect that makes the framed viewport ~1200x1500 CSS px on a 240px card —
   a desktop-width page, about two laptop screens deep, so the hero, the band
   under it, and the start of the third are all in frame. Templates differ
   there; they did not in the top 500px.

   Caveat worth knowing: `vh` inside the frame resolves against the FRAMED
   height, not a notional screen, so a `min-height: 60vh` hero still takes 60%
   of the card no matter how tall we make it. Depth beyond ~2 screens buys
   nothing; it just shrinks the type. */
.gg-tpl-thumb {
  /* `display: block` is load-bearing: the in-editor quick-add card renders this
     as a <span> (it lives inside a <button>, which may not contain a <div>). */
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

.gg-tpl-thumb iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 500%;
  height: 500%;
  border: 0;
  transform: scale(0.2);
  transform-origin: top left;
  pointer-events: none;
}

/* Create a site's starts without a template (Blank site, Built elsewhere):
   no template to frame, so the thumbnail draws the start from tokens: a page
   with its header and footer bars around an empty canvas. Spans throughout —
   the card is a <button>. */
.gg-start-thumb {
  display: flex;
  flex: 0 0 6.5rem;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background: var(--surface-2);
  border-right: 1px solid var(--line);
}

.gg-start-page {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  aspect-ratio: 4 / 5;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--surface);
}

.gg-start-bar {
  display: block;
  height: 6px;
  border-radius: 2px;
  background: var(--line);
}

.gg-start-canvas {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--line);
  border-radius: 2px;
  color: var(--faint);
  font-size: 11px;
  font-weight: 600;
}

/* Frame that owns the preview pill's positioning. The card itself is a
   <button> (clicking it creates), so the anchor cannot live inside it — this
   wrapper makes them siblings and stretches the card to the grid cell. */
.gg-tpl-card {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* "Preview" click-through — the secondary affordance on a template card. The
   card itself still CREATES on click, so this is a real anchor (new tab) laid
   over the thumbnail's top-right rather than a nested button, which HTML
   forbids. Deliberately quiet: a pill in --faint that only reaches --ink on
   hover, so it never competes with the card's own action. */
.gg-tpl-preview {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--faint);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  text-decoration: none;
  opacity: 0.9;
}

.gg-tpl-preview:hover,
.gg-tpl-preview:focus-visible {
  border-color: var(--gold-1);
  color: var(--ink);
  opacity: 1;
}

.gg-tp-card {
  display: flex;

  /* Fills its .gg-tpl-card frame (always its parent) so the pill lands on the
     card's own corner rather than a wider grid cell. */
  flex: 1;
  min-width: 0;
  flex-direction: column;
  text-align: left;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
  cursor: pointer;
  transition:
    box-shadow 0.15s,
    border-color 0.15s,
    transform 0.15s;
  font: inherit;
}

.gg-tp-card:disabled {
  opacity: 0.6;
  cursor: default;
}

.gg-tp-card:hover:not(:disabled) {
  border-color: var(--gold-1);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

/* Site-card thumbnail: render the page's live preview at 4x the card's own
   size and scale it back down by exactly 1/4, so the frame always fills the
   card edge-to-edge no matter how wide the grid makes it (the percentages
   track the wrapper, unlike a hard-coded pixel scale). Still the right shape
   for a SITE card (one existing page, wide strip); template cards use
   .gg-tpl-thumb above. */
.gg-lp-card-thumb iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 400%;
  height: 400%;
  border: 0;
  transform: scale(0.25);
  transform-origin: top left;
  pointer-events: none;
}

/* Pages-list row thumbnail: the page's own preview laid out at a desktop
   width (1100px) and scaled to the 88px tile (88 / 1100 = 0.08), so a row
   shows the page as a visitor's screen does, not its phone layout. */
.gg-page-thumb {
  position: relative;
  flex: 0 0 auto;
  width: 88px;
  height: 56px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--surface-2);
}

.gg-page-thumb iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1100px;
  height: 700px;
  border: 0;
  transform: scale(0.08);
  transform-origin: top left;
  pointer-events: none;
}

.gg-page-thumb-blank {
  display: grid;
  place-items: center;
  height: 100%;
  background: var(--surface-2);
  color: var(--faint);
  font-size: 10px;
}

.gg-tp-body {
  padding: 14px 16px 18px;
}

.gg-tp-name {
  font-size: 16px;
  font-weight: 650;
  color: var(--ink);
  margin: 0 0 4px;
}

.gg-tp-desc {
  font-size: 13px;
  line-height: 1.45;
  color: var(--muted);
  margin: 0;
}

.gg-tp-creating {
  font-size: 12px;
  font-weight: 600;
  color: var(--gold-text);
  margin-top: 8px;
}

.gg-tp-blank {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

.gg-tp-blank-btn {
  padding: 10px 18px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.gg-tp-blank-btn:hover:not(:disabled) {
  background: var(--surface-2);
}

.gg-tp-state {
  padding: 48px 0;
  text-align: center;
  color: var(--muted);
}

/* Landing-page version history (landing-builder/history). Same plain global
   rules as the template gallery; classes are gg-vh-* namespaced. */
.gg-version-history {
  max-width: 880px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.gg-vh-head {
  margin-bottom: 24px;
}

.gg-vh-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--ink);
  margin: 12px 0 4px;
}

.gg-vh-sub {
  font-size: 15px;
  color: var(--muted);
  margin: 0;
}

.gg-vh-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.gg-vh-item {
  display: flex;
  gap: 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
}

.gg-vh-preview {
  position: relative;
  flex: 0 0 240px;
  height: 180px;
  background: var(--surface-2);
  border-right: 1px solid var(--line);
  overflow: hidden;
}

.gg-vh-preview iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1200px;
  height: 900px;
  border: 0;
  transform: scale(0.2);
  transform-origin: top left;
  pointer-events: none;
}

.gg-vh-no-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 13px;
  color: var(--faint);
}

.gg-vh-body {
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

.gg-vh-version {
  font-size: 16px;
  font-weight: 650;
  color: var(--ink);
  margin: 0;
}

.gg-vh-current {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--gold-text);
  font-size: 11px;
  font-weight: 600;
  vertical-align: middle;
}

.gg-vh-summary {
  font-size: 14px;
  color: var(--muted);
  margin: 0;
}

.gg-vh-date {
  font-size: 13px;
  color: var(--muted);
  margin: 0;
}

.gg-vh-restore-btn {
  margin-top: auto;
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.gg-vh-restore-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.gg-vh-restore-btn:hover:not(:disabled) {
  border-color: var(--gold-1);
  color: var(--gold-text);
}

.gg-vh-unrestorable {
  margin-top: auto;
  font-size: 12px;
  color: var(--faint);
}

.gg-vh-more {
  margin-top: 20px;
  text-align: center;
}

.gg-vh-state {
  padding: 48px 0;
  text-align: center;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

/* Cloudflare Turnstile (TurnstileField). The widget is a cross-origin iframe,
   so only its box can be shaped: full row width (paired with size:'flexible'
   in lib/turnstile.ts) and clipped corners, so a visible challenge sits in
   the form like a field instead of a fixed 300px card. */
.gg-turnstile {
  width: 100%;
}

.gg-turnstile iframe {
  display: block;
  max-width: 100%;
  border-radius: 8px;
}
