/* ============================================================
   YIZZOO - Pages
   Everything that is not the homepage: page headers, article
   bodies, content blocks, product pages, listings.
   ============================================================ */

/* ============================================================
   PAGE HEADER + BREADCRUMB (blueprint 40)
   ============================================================ */
.yz-pagehead{
  background: var(--color-parchment);
  padding-block: var(--sp-9) var(--sp-7);
  border-bottom: 1px solid var(--color-border);
}
.yz-pagehead h1{
  font-size: var(--fs-page);
  line-height: var(--lh-page);
  max-width: var(--header-max);
  margin: 0;
}
.yz-pagehead__lead{
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  color: var(--color-soft-ink);
  max-width: 640px;
  margin: var(--sp-3) 0 0;
}

.yz-crumbs{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-crumbs a{ color: var(--color-teal); text-decoration: none; }
.yz-crumbs a:hover{ text-decoration: underline; }
.yz-crumbs__sep{ opacity: 0.45; }

/* ============================================================
   FILTER CHIPS (blueprint 41)
   Static until there is a database to filter. A control that looks
   interactive and does nothing is worse than one that is honestly
   not there yet, so these do not pretend to be buttons.
   ============================================================ */
.yz-filters{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  padding-block: var(--sp-6);
}
.yz-filter{ display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.yz-filter__label{
  font-size: var(--fs-meta);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-soft-ink);
  margin-right: 2px;
}
.yz-chip--static{ cursor: default; opacity: 0.85; }
.yz-chip--static:hover{
  border-color: var(--color-border);
  background: var(--color-parchment);
  color: var(--color-ink);
}
a.yz-chip{ text-decoration: none; }

/* ============================================================
   LINK GRID - the idea categories
   ============================================================ */
.yz-linkgrid{
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--sp-4);
}
.yz-linkcard{
  display: block;
  padding: var(--sp-5);
  background: var(--color-paper);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-gold-30);
  border-radius: var(--radius-card);
  text-decoration: none;
  color: inherit;
  transition: transform var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              border-left-color var(--t-base) var(--ease);
}
.yz-linkcard:hover{
  transform: translateY(-3px);
  box-shadow: var(--shadow-card);
  border-left-color: var(--color-gold);
  color: inherit;
}
.yz-linkcard svg{ color: var(--color-teal); margin-bottom: var(--sp-3); }
.yz-linkcard__name{
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  line-height: var(--lh-h4);
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 24;
  color: var(--color-midnight);
  margin-bottom: 4px;
}
.yz-linkcard__desc{
  display: block;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--color-soft-ink);
}

/* ============================================================
   ARTICLE (blueprint 30-32)
   Reading width 720px. Never wider, whatever the screen.
   ============================================================ */
.yz-article__meta{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  padding-block: var(--sp-5);
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-article__meta > span{ display: inline-flex; align-items: center; gap: 6px; }
.yz-article__meta svg{ color: var(--color-teal); }

.yz-article__hero{
  max-width: var(--wide-max);
  margin: 0 auto var(--sp-8);
  padding-inline: var(--page-pad);
}
.yz-article__hero picture,
.yz-article__hero img{
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

.yz-article__body{
  max-width: var(--reading-max);
  margin: 0 auto;
  padding: 0 var(--page-pad) var(--sp-10);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.yz-article__body h2{
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  margin: var(--sp-8) 0 var(--sp-3);
}
.yz-article__body h3{
  font-size: var(--fs-h4);
  line-height: var(--lh-h4);
  margin: var(--sp-6) 0 var(--sp-2);
}
.yz-article__body p{ margin: 0 0 var(--sp-4); }
.yz-article__body code{
  font-family: "Courier New", ui-monospace, monospace;
  font-size: 0.94em;
  letter-spacing: 0.06em;
  background: var(--color-gold-12);
  padding: 2px 6px;
  border-radius: 4px;
  color: #7d5f1c;
}

.yz-bullets, .yz-steps{ margin: 0 0 var(--sp-5); padding-left: var(--sp-5); }
.yz-bullets li, .yz-steps li{ margin-bottom: var(--sp-3); }
.yz-bullets{ list-style: none; padding-left: 0; }
.yz-bullets > li{ position: relative; padding-left: var(--sp-5); }
.yz-bullets > li::before{
  content: "";
  position: absolute;
  left: 4px; top: 0.62em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--color-gold);
}
.yz-steps{ counter-reset: step; list-style: none; padding-left: 0; }
.yz-steps > li{ position: relative; padding-left: var(--sp-7); }
.yz-steps > li::before{
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0; top: 0.1em;
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--color-teal);
  color: var(--color-paper);
  font-size: 13px;
  font-weight: 800;
}

/* ============================================================
   BRANDED CALLOUTS (design doc 16, blueprint 33-35)
   These are what make a Yizzoo guide recognisable as one.
   ============================================================ */
.yz-callout{
  margin: var(--sp-6) 0;
  padding: var(--sp-5);
  border-radius: var(--radius-card);
  background: var(--color-paper);
  border: 1px solid var(--color-border);
}
.yz-callout__label{
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-meta);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-weight: 800;
}
.yz-callout__body{ font-size: var(--fs-small); line-height: var(--lh-body); }
.yz-callout__body p:last-child{ margin-bottom: 0; }

/* Quest Tip: warm cream paper with a gold star. */
.yz-callout--tip{ background: #FBF3DC; border-color: var(--color-gold-30); }
.yz-callout--tip .yz-callout__label{ color: #8A6A21; }

/* Designer Note: a dark teal left border. The one Selfdefiant writes. */
.yz-callout--note{ border-left: 4px solid var(--color-teal); }
.yz-callout--note .yz-callout__label{ color: var(--color-teal); }

/* Make It Easier / Harder: a matched pair. */
.yz-callout--easier{ border-left: 4px solid var(--color-sage); }
.yz-callout--easier .yz-callout__label{ color: #4F6047; }
.yz-callout--harder{ border-left: 4px solid var(--color-red); }
.yz-callout--harder .yz-callout__label{ color: var(--color-red); }

.yz-callout--mistake{ background: rgba(165,79,67,0.06); border-color: rgba(165,79,67,0.3); }
.yz-callout--mistake .yz-callout__label{ color: var(--color-red); }

.yz-callout--shortcut{ border-left: 4px solid var(--color-coral); }
.yz-callout--shortcut .yz-callout__label{ color: var(--color-coral-dark); }

/* Puzzle example: set like a clue card. */
.yz-example{
  margin: var(--sp-6) 0;
  padding: var(--sp-5);
  background: var(--color-paper);
  border: 1px solid var(--color-border);
  border-top: 3px solid var(--color-coral);
  border-radius: var(--radius-card);
  text-align: center;
}
.yz-example figcaption{
  font-size: var(--fs-meta);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--color-coral);
  margin-bottom: var(--sp-3);
}
.yz-example__body{ font-size: var(--fs-intro); }
.yz-example code{ font-size: 1.05em; letter-spacing: 0.24em; }

.yz-materials{
  margin: var(--sp-6) 0;
  padding: var(--sp-5);
  background: var(--color-parchment);
  border-radius: var(--radius-card);
}
.yz-materials h3{ margin: 0 0 var(--sp-3); font-size: var(--fs-h4); }
.yz-materials ul{ list-style: none; margin: 0; padding: 0; }
.yz-materials li{
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
  font-size: var(--fs-small);
}
.yz-materials svg{ color: var(--color-sage); flex: none; margin-top: 3px; }

/* An inline product, mid-article (design doc 38). */
.yz-inline-product{
  display: flex;
  gap: var(--sp-4);
  align-items: center;
  margin: var(--sp-7) 0;
  padding: var(--sp-4);
  background: var(--color-midnight);
  border-radius: var(--radius-card);
  color: rgba(255,253,247,0.82);
}
.yz-inline-product__art{
  flex: none;
  width: 110px;
  border-radius: var(--radius-control);
  overflow: hidden;
}
.yz-inline-product__art picture,
.yz-inline-product__art img,
.yz-inline-product__art svg{ display: block; width: 100%; height: auto; }
.yz-inline-product__body .yz-eyebrow{ color: var(--color-gold); margin-bottom: 4px; }
.yz-inline-product__title{
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 24;
  color: #FFFDF7;
  margin: 0 0 var(--sp-2);
}
.yz-inline-product__text{ font-size: var(--fs-small); margin: 0 0 var(--sp-3); }

.yz-ad--inline{ margin-block: var(--sp-7); min-height: 250px; max-width: 100%; }

/* ============================================================
   PRODUCT PAGE (blueprint 36-39)
   ============================================================ */
.yz-product-hero{ background: var(--color-parchment); padding-block: var(--sp-9); }
.yz-product-hero__inner{
  display: grid;
  grid-template-columns: 460px 1fr;
  gap: var(--sp-9);
  align-items: start;
}
.yz-product-hero__art svg{ width: 100%; height: auto; border-radius: var(--radius-card); }
.yz-product-hero__body h1{
  font-size: var(--fs-page);
  line-height: var(--lh-page);
  margin: 0 0 var(--sp-3);
}
.yz-product-hero__lead{
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  color: var(--color-soft-ink);
  margin: 0 0 var(--sp-6);
}

.yz-facts{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: var(--sp-4);
  margin: 0 0 var(--sp-7);
  padding: var(--sp-5);
  background: var(--color-paper);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
}
.yz-facts dt{
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-meta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-soft-ink);
  margin-bottom: 4px;
}
.yz-facts dt svg{ color: var(--color-teal); }
.yz-facts dd{
  margin: 0;
  font-family: var(--font-display);
  font-size: 19px;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 22;
  color: var(--color-midnight);
}

.yz-product-hero__buy{
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.yz-product-hero__price{
  font-family: var(--font-display);
  font-size: 34px;
  line-height: 1;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 36;
  color: var(--color-midnight);
}
.yz-product-hero__note{
  display: flex;
  align-items: center;
  gap: 7px;
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-product-hero__note svg{ color: var(--color-sage); flex: none; }

.yz-checklist{ list-style: none; margin: 0 0 var(--sp-8); padding: 0; }
.yz-checklist li{
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.yz-checklist svg{ color: var(--color-sage); flex: none; margin-top: 4px; }

@media (max-width: 1023px){
  .yz-product-hero__inner{ grid-template-columns: 1fr; gap: var(--sp-7); }
  .yz-product-hero__art{ max-width: 420px; }
}

/* ============================================================
   PROSE + PANELS
   ============================================================ */
.yz-prose{ padding-block: var(--sp-8) var(--sp-10); font-size: var(--fs-body); }
.yz-prose h2{ font-size: var(--fs-h3); line-height: var(--lh-h3); margin: var(--sp-7) 0 var(--sp-3); }
.yz-prose p{ margin: 0 0 var(--sp-4); }

/* Legal pages. Long prose, so the measure is tighter and the headings
   are given more air than an article's - somebody scanning for the one
   paragraph that applies to them is navigating by heading. */
.yz-legal h2{
  margin-top: var(--sp-9);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--color-border);
}
.yz-legal h2:first-of-type{ border-top: 0; padding-top: 0; }
.yz-legal .yz-bullets{ margin-bottom: var(--sp-5); }
.yz-legal code{
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--color-teal-08);
  font-size: 0.92em;
}
.yz-legal-date{
  margin-bottom: var(--sp-6);
  font-size: var(--fs-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-soft-ink);
}

.yz-panel{
  margin-block: var(--sp-8) var(--sp-10);
  padding: var(--sp-7);
  background: var(--color-paper);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-card);
}
.yz-panel p{ margin-bottom: var(--sp-5); }

.yz-empty{
  padding: var(--sp-7) 0;
  text-align: center;
  font-size: var(--fs-intro);
  color: var(--color-soft-ink);
}

.yz-search__field--page{ max-width: 640px; margin-top: var(--sp-6); }

/* ============================================================
   PREVIEW
   Only ever rendered for someone who asked for ?preview=1, so it
   is allowed to look like a tool rather than like the site.
   ============================================================ */
.yz-draftbar{
  margin: 0 0 var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-control);
  background: var(--color-midnight);
  color: var(--color-gold);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.yz-callout.is-draft{
  border-style: dashed;
  background: repeating-linear-gradient(
    -45deg, transparent 0 9px, rgba(211,164,70,0.07) 9px 18px);
}
.yz-callout__draft{
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--color-gold);
  color: var(--color-midnight);
  font-size: 10px;
  letter-spacing: 0.08em;
}

/* ============================================================
   ADMIN BAR + SIGN IN
   Only ever rendered for a signed-in admin, so it is allowed to
   look like a tool rather than like the site.
   ============================================================ */
.yz-adminbar{
  /* Sticky, above the header, and higher in the stack so the header
     slides under it rather than over it. It is the one thing on the
     page that must stay reachable from anywhere in a long guide: what
     is unfinished, and the way out. */
  position: sticky;
  top: 0;
  z-index: 300;               /* .yz-header is 200 */
  background: var(--color-midnight);
  color: rgba(255,253,247,0.80);
  font-size: var(--fs-small);
}

/* The site header is sticky at top:0 for everybody else. With the
   admin bar above it, it has to stop that far down instead, or the
   two occupy the same strip and one covers the other. */
body.has-adminbar .yz-header{ top: var(--adminbar-h); }

/* MEASURED, not guessed: 51px at 1280 and 49px at 390 on 2026-09-18.
   yizzoo.js overwrites this with the real height on load and on
   resize, so the number here only has to be close enough that nothing
   jumps before the script runs. It does not have to stay true if the
   bar's contents change. */
body.has-adminbar{ --adminbar-h: 51px; }
.yz-adminbar__inner{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  min-height: 40px;
  padding-block: 8px;
}
.yz-adminbar__tag{
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--color-gold);
  color: var(--color-midnight);
  font-size: var(--fs-meta);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.yz-adminbar__warn{ color: var(--color-gold); }
.yz-adminbar__link{
  margin-left: auto;
  color: rgba(255,253,247,0.80);
  text-decoration: none;
  font-weight: 700;
}
.yz-adminbar__link + .yz-adminbar__link{ margin-left: var(--sp-4); }
.yz-adminbar__link:hover{ color: var(--color-gold); }

.yz-label{
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-meta);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-soft-ink);
}
.yz-input{
  width: 100%;
  height: 48px;
  margin-bottom: var(--sp-4);
  padding: 0 var(--sp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  background: var(--color-parchment);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--color-ink);
}
.yz-input:focus{ outline: none; border-color: var(--color-teal); }
.yz-formerror{
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-control);
  background: rgba(165,79,67,0.09);
  color: var(--color-red);
  font-size: var(--fs-small);
  font-weight: 600;
}

/* The same shape as the error, in the affirmative. Same box so a page
   that swaps one for the other does not jump. */
.yz-formok{
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-control);
  background: rgba(118,136,106,0.12);
  color: var(--color-sage);
  font-size: var(--fs-small);
  font-weight: 600;
}
.yz-formhint{
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-formhint a{ color: var(--color-teal); font-weight: 600; }

/* The admin to-do: what is unfinished, with a route to each one. */
.yz-todo{ margin: 0 0 var(--sp-5); padding: 0; list-style: none; counter-reset: todo; }
.yz-todo__item{
  counter-increment: todo;
  position: relative;
  padding: var(--sp-4) 0 var(--sp-4) var(--sp-8);
  border-top: 1px solid var(--color-border);
}
.yz-todo__item::before{
  content: counter(todo);
  position: absolute;
  left: 0;
  top: var(--sp-4);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--color-gold);
  color: var(--color-ink);
  font-size: 12px;
  font-weight: 800;
  line-height: 22px;
  text-align: center;
}
.yz-todo__link{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  color: var(--color-teal);
  text-decoration: none;
}
.yz-todo__link:hover{ text-decoration: underline; }
.yz-todo__note{
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--color-soft-ink);
}

/* The count in the admin bar, now that it goes somewhere. */
.yz-adminbar__todo{
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.yz-adminbar__todo:hover{ color: var(--color-gold); }

/* The note being linked to, once you land on it. Brief, because a
   highlight that never fades becomes part of the design.

   scroll-margin-top clears the sticky header. Without it the browser
   scrolls the anchor to y=0, which is underneath the header, and the
   link looks broken in the one way that is hardest to describe: it
   goes to the right place and shows you the wrong thing. */
.yz-callout.is-draft:target,
.yz-draftbar:target{
  scroll-margin-top: calc(var(--header-h) + var(--adminbar-h, 0px) + var(--sp-5));
}
.yz-callout.is-draft:target{
  animation: yz-flash 2.2s ease-out 1;
}
@keyframes yz-flash{
  0%, 40% { box-shadow: 0 0 0 3px var(--color-gold); }
  100%    { box-shadow: 0 0 0 3px rgba(0,0,0,0); }
}
@media (prefers-reduced-motion: reduce){
  .yz-callout.is-draft:target{ animation: none; box-shadow: 0 0 0 3px var(--color-gold); }
}

/* Sign in. Google renders its own button into .g_id_signin and we do
   not restyle it - a sign-in button people do not recognise is a
   sign-in button people do not press, and Google's terms require its
   own branding anyway. All we control is what sits around it. */
.yz-signin{ text-align: center; }
.yz-signin__btn{
  display: flex;
  justify-content: center;
  /* Reserves the button's height so the panel does not jump when
     Google's script finishes loading. */
  min-height: 44px;
  margin: var(--sp-4) 0 var(--sp-6);
}
.yz-signin__note{
  margin: 0;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--color-soft-ink);
  text-align: left;
}
.yz-signin__note a{ color: var(--color-teal); font-weight: 600; }

/* My Adventures: what somebody owns. */
.yz-owned{ display: grid; gap: var(--sp-4); margin-bottom: var(--sp-6); }
.yz-owned__item{
  display: flex;
  gap: var(--sp-5);
  align-items: center;
  padding: var(--sp-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-paper);
  box-shadow: var(--shadow-card);
}
.yz-owned__art{
  flex: none;
  width: 120px;
  border-radius: var(--radius-control);
  overflow: hidden;
}
.yz-owned__art img,
.yz-owned__art svg{ display: block; width: 100%; height: auto; }
.yz-owned__body{ min-width: 0; }
.yz-owned__title{
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-h4);
  line-height: 1.25;
}
.yz-owned__meta{
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
@media (max-width: 560px){
  .yz-owned__item{ flex-direction: column; align-items: flex-start; }
  .yz-owned__art{ width: 100%; max-width: 180px; }
}

/* ============================================================
   THE BLOCK EDITOR  (blueprint 56-58)

   Only ever in the DOM for a signed-in admin, so none of this
   costs a visitor anything. The rule it follows: the block being
   edited must stay exactly where it is on the page. An editor
   that lifts content into a modal is an editor where you cannot
   see what the paragraph above says.
   ============================================================ */
.yz-ed{
  position: relative;
  margin: 0 0 var(--sp-2);
  border-radius: var(--radius-control);
  transition: background var(--t-base) var(--ease);
}
.yz-ed:hover{ background: var(--color-teal-08); }
.yz-ed.is-editing{
  background: var(--color-teal-08);
  outline: 2px solid var(--color-teal);
  outline-offset: 4px;
}
/* The bar sits outside the reading column on a wide screen and folds
   in above the block when there is no room beside it. */
.yz-ed__bar{
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-2) 0 var(--sp-3);
  /* Visible, not hover-only. A control you have to discover by waving
     the mouse at the right paragraph is a control that does not exist:
     the first build of this hid the bar until hover and the edit
     button could not be found at all. Muted until you approach it, so
     it stays out of the way of reading without ever being absent. */
  opacity: 0.55;
  transition: opacity var(--t-base) var(--ease);
}
.yz-ed:hover .yz-ed__bar,
.yz-ed.is-editing .yz-ed__bar,
.yz-ed:focus-within .yz-ed__bar{ opacity: 1; }

.yz-ed__type{
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--color-soft-ink);
  margin-right: auto;
}
.yz-ed__btn{
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-paper);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-ink);
  cursor: pointer;
}
.yz-ed__btn:hover{ border-color: var(--color-teal); color: var(--color-teal); }
.yz-ed__btn:disabled{ opacity: 0.5; cursor: default; }
.yz-ed__btn--go{ background: var(--color-teal); border-color: var(--color-teal); color: #fff; }
.yz-ed__btn--go:hover{ background: var(--color-ink); border-color: var(--color-ink); color: #fff; }

/* Save and Cancel only exist while editing; Undo only when there is
   something to undo. A button that does nothing is worse than an
   absent one, because it invites the press that teaches you that. */
.yz-ed .is-editing{ display: none; }
.yz-ed.is-editing .is-editing{ display: inline-flex; }
.yz-ed.is-editing [data-act="edit"]{ display: none; }
.yz-ed[data-undo="0"] .yz-ed__btn--undo{ display: none; }

.yz-ed__input{
  display: block;
  width: 100%;
  min-height: 120px;
  padding: var(--sp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-paper);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--color-ink);
  resize: vertical;
}
.yz-ed__input:focus{ outline: none; border-color: var(--color-teal); }
.yz-ed__hint{
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-ed__status{ font-size: 12px; font-weight: 700; }
.yz-ed__status.is-good{ color: var(--color-sage); }
.yz-ed__status.is-bad{ color: var(--color-red); }

/* While editing, the rendered copy is context rather than the thing
   being worked on, so it steps back instead of competing. */
.yz-ed.is-editing .yz-ed__view{ opacity: 0.45; }

@media (hover: none){
  /* No hover on a touch screen, so it is simply always at full. */
  .yz-ed__bar{ opacity: 1; }
}

/* --- editor: move, delete, add, restore, retitle ------------- */

/* Icon-only and quieter than the text buttons. Move and delete are
   used far less than Edit, and one of them is destructive, so neither
   should sit under the cursor by accident. */
.yz-ed__minor{ display: inline-flex; gap: 4px; }
.yz-ed__icon{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid transparent;
  border-radius: 50%;
  background: none;
  color: var(--color-soft-ink);
  cursor: pointer;
}
.yz-ed__icon:hover{ border-color: var(--color-border); color: var(--color-ink); }
.yz-ed__icon--danger:hover{ border-color: var(--color-red); color: var(--color-red); }
.yz-ed__up{ transform: rotate(180deg); }

/* Add-below sits under the block it adds after, and only shows when
   that block is being approached, so an article is not a ladder of
   Add buttons when you are reading it. */
.yz-ed__add{
  padding-bottom: var(--sp-3);
  /* Faint rather than absent. At zero it left a dead gap between
     every pair of blocks that read as broken spacing, and repeated
     the mistake the edit bar already made: a control you have to
     discover by hovering the right spot is not a control. */
  opacity: 0.3;
  transition: opacity var(--t-base) var(--ease);
}
.yz-ed:hover .yz-ed__add,
.yz-ed:focus-within .yz-ed__add{ opacity: 1; }
@media (hover: none){ .yz-ed__add{ opacity: 1; } }

.yz-ed__addbtn{
  width: 100%;
  padding: 5px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-control);
  background: none;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-soft-ink);
  cursor: pointer;
}
.yz-ed__addbtn:hover{ border-color: var(--color-teal); color: var(--color-teal); }
.yz-ed__addpick{ display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.yz-ed__type-select{
  flex: 1 1 160px;
  height: 34px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  background: var(--color-paper);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--color-ink);
}

/* Deleted blocks, recoverable. Shown rather than hidden in a table
   only I can read, because a Restore nobody can find is not one. */
.yz-gone{
  margin-top: var(--sp-8);
  padding: var(--sp-5);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-parchment);
}
.yz-gone__title{
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-meta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--color-soft-ink);
}
.yz-gone__list{ list-style: none; margin: 0; padding: 0; }
.yz-gone__item{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-small);
}
.yz-gone__item:first-child{ border-top: 0; }
.yz-gone__type{
  flex: none;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--color-soft-ink);
}
.yz-gone__text{
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-soft-ink);
}

/* The guide's own title and excerpt. */
.yz-ed-article{ padding-bottom: var(--sp-4); }
.yz-ed-article__edit{ padding-bottom: var(--sp-3); }
.yz-ed-article .yz-ed__bar{ opacity: 0.55; }
.yz-ed-article:hover .yz-ed__bar,
.yz-ed-article.is-editing .yz-ed__bar{ opacity: 1; }
.yz-ed-article .is-editing{ display: none; }
.yz-ed-article.is-editing .is-editing{ display: inline-flex; }
.yz-ed-article.is-editing [data-act="title-edit"]{ display: none; }

/* The URL field on the new-guide form: the prefix is fixed text, not
   something to be typed or edited. */
.yz-slugrow{ display: flex; align-items: center; gap: var(--sp-2); }
.yz-slugrow__prefix{
  flex: none;
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--color-soft-ink);
}
.yz-slugrow .yz-input{ margin-bottom: 0; }

/* Every guide, on /admin. Drafts included and marked, because a draft
   you cannot find again is a draft you rewrite from scratch. */
.yz-guidelist{ list-style: none; margin: var(--sp-5) 0 0; padding: 0; }
.yz-guidelist__item{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-small);
}
.yz-guidelist__item a{ color: var(--color-teal); font-weight: 600; text-decoration: none; }
.yz-guidelist__item a:hover{ text-decoration: underline; }
.yz-guidelist__draft{
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-gold);
  color: var(--color-midnight);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* --- pictures in a guide ------------------------------------ */

/* The figure's WIDTH is set inline from the block's scale, because it
   is per-picture data rather than a design decision. Everything else
   about it lives here. */
.yz-figure{
  margin: var(--sp-7) 0;
  max-width: 100%;
}
.yz-figure img{
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
}
.yz-figure figcaption{
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--color-soft-ink);
}
.yz-figure--center{ margin-left: auto; margin-right: auto; }
.yz-figure--left{ margin-right: auto; }
.yz-figure--right{ margin-left: auto; }
.yz-figure--left figcaption{ text-align: left; }
.yz-figure--right figcaption{ text-align: right; }
.yz-figure--center figcaption{ text-align: center; }

/* On a phone a picture scaled to 40% of a 720px column is a thumbnail
   nobody can see. Below the breakpoint every picture is full width and
   the scale is ignored, which is why the inline width is overridden
   rather than removed. */
@media (max-width: 600px){
  .yz-figure{ width: 100% !important; }
}

/* --- the picture controls ----------------------------------- */
.yz-imgctl{ margin-bottom: var(--sp-4); }
.yz-imgctl__file{
  display: block;
  width: 100%;
  margin-bottom: var(--sp-1);
  font-family: var(--font-body);
  font-size: var(--fs-small);
}
.yz-imgctl__row{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.yz-imgctl__scale{ flex: 1; accent-color: var(--color-teal); }
.yz-imgctl__out{
  flex: none;
  min-width: 48px;
  font-size: var(--fs-small);
  font-weight: 800;
  color: var(--color-teal);
  text-align: right;
}
.yz-imgctl__align{
  padding: 5px 13px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-soft-ink);
  cursor: pointer;
}
.yz-imgctl__align input{ position: absolute; opacity: 0; pointer-events: none; }
.yz-imgctl__align.is-on{
  border-color: var(--color-teal);
  background: var(--color-teal);
  color: #fff;
}

/* --- the pin maker, on a guide ------------------------------ */
.yz-pinmake{ padding-top: var(--sp-3); }
.yz-pinmake__form{ padding: var(--sp-4) 0; }
.yz-pinmake__made{
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-top: var(--sp-4);
}
.yz-pinmake__thumb img{
  display: block;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
}

/* --- the queue --------------------------------------------- */
.yz-pinfilter{ display: flex; gap: var(--sp-4); margin: var(--sp-6) 0 var(--sp-5); }
.yz-pinfilter__link{
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--color-soft-ink);
  text-decoration: none;
  padding-bottom: 4px;
  border-bottom: 2px solid transparent;
}
.yz-pinfilter__link.is-on{ color: var(--color-teal); border-bottom-color: var(--color-teal); }

.yz-pinlist{ display: grid; gap: var(--sp-5); margin-bottom: var(--sp-10); }
.yz-pincard{
  display: flex;
  gap: var(--sp-5);
  padding: var(--sp-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-paper);
}
/* The pin itself, at the size it will be seen in a feed. Judging a
   1000x1500 image at full size tells you nothing about whether the
   headline survives a thumbnail, which is the only thing that matters. */
.yz-pincard__shot{ flex: none; }
.yz-pincard__shot img{
  display: block;
  width: 200px;
  height: auto;
  border-radius: var(--radius-control);
  border: 1px solid var(--color-border);
}
.yz-pincard__body{ flex: 1; min-width: 0; }
.yz-pincard__meta{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-small);
}
.yz-pincard__meta a{ color: var(--color-teal); font-weight: 600; text-decoration: none; }
.yz-pincard__status{
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.yz-pincard__status.is-draft{ background: var(--color-border); color: var(--color-ink); }
.yz-pincard__status.is-queued{ background: var(--color-gold); color: var(--color-midnight); }
.yz-pincard__status.is-posted{ background: var(--color-sage); color: #fff; }
.yz-pincard__row{ display: flex; align-items: center; gap: var(--sp-3); }
.yz-pincard__row .yz-label{ margin: 0; }
.yz-pincard__row .yz-input{ width: auto; margin: 0; }
.yz-pincard__actions{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.yz-pincard__url{
  margin: var(--sp-3) 0 0;
  font-size: 12px;
  color: var(--color-soft-ink);
  word-break: break-all;
}
@media (max-width: 720px){
  .yz-pincard{ flex-direction: column; }
  .yz-pincard__shot img{ width: 160px; }
}

/* --- editing a product -------------------------------------- */
.yz-ed-product{ padding: var(--sp-4) 0 0; }
.yz-ed-product__edit{ padding-bottom: var(--sp-4); }
.yz-ed-product .yz-ed__bar{ opacity: 0.55; }
.yz-ed-product:hover .yz-ed__bar,
.yz-ed-product.is-editing .yz-ed__bar{ opacity: 1; }
.yz-ed-product .is-editing{ display: none; }
.yz-ed-product.is-editing .is-editing{ display: inline-flex; }
.yz-ed-product.is-editing [data-act="prod-edit"]{ display: none; }

/* The numbers that only make sense beside each other - age from/to,
   players from/to - sit on one row so they can be read as a range. */
.yz-edgrid__row{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-bottom: var(--sp-3);
}
.yz-edgrid__row > span{ flex: 1 1 140px; min-width: 0; }
.yz-edgrid__row .yz-input{ margin-bottom: 0; }

/* --- the Questboard manager --------------------------------- */
.yz-qbadmin{
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: var(--sp-5);
  margin-bottom: var(--sp-10);
}
.yz-qbcard{
  padding: var(--sp-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-paper);
}
/* A piece switched off is dimmed rather than hidden: its slot still
   exists on the board and it still has to be findable to switch back. */
.yz-qbcard.is-off{ opacity: 0.55; }
.yz-qbcard.is-off:hover{ opacity: 1; }
.yz-qbcard__head{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--color-border);
}
.yz-qbcard__slot{
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--color-teal);
}
.yz-qbcard__toggle{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--color-soft-ink);
  cursor: pointer;
}
.yz-qbcard__toggle input{ accent-color: var(--color-teal); }
.yz-qbcard .yz-label{ margin-top: var(--sp-3); }
.yz-qbcard .yz-input,
.yz-qbcard .yz-ed__input{ margin-bottom: 0; }
.yz-qbcard__actions{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

/* --- the homepage manager ----------------------------------- */
.yz-seclist{ list-style: none; margin: 0 0 var(--sp-10); padding: 0; }
.yz-seccard{
  padding: var(--sp-5);
  margin-bottom: var(--sp-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-paper);
}
.yz-seccard.is-off{ opacity: 0.5; }
.yz-seccard.is-off:hover{ opacity: 1; }
.yz-seccard__head{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.yz-seccard__name{ font-weight: 800; font-size: var(--fs-body); }
/* The key is shown because it is what the renderer is called, and
   hidden keys are how somebody ends up unable to say which band is
   which. It is not an input: a typo in it is a band that vanishes. */
.yz-seccard__key{
  margin-left: var(--sp-2);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--color-soft-ink);
  background: var(--color-teal-08);
  padding: 2px 7px;
  border-radius: 999px;
}
.yz-seccard__tools{ display: flex; align-items: center; gap: var(--sp-3); }
.yz-seccard__what{
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-small);
  color: var(--color-soft-ink);
}
.yz-seccard .yz-label{ margin-top: var(--sp-4); }
.yz-seccard .yz-input,
.yz-seccard .yz-ed__input{ margin-bottom: 0; }
.yz-seccard__actions{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}
