/* Gooki storefront, "alive" layer (2026-09).
 *
 * Loaded LAST, after style.css, storefront-redesign.css and gooki-redesign.css.
 * The spec is src/gook_web/DESIGN.md. Three jobs:
 *
 *   1. Re-point the shared tokens (serif face, palette, buttons, masthead,
 *      footer) so every page — orders, auth, legal included — takes the new look
 *      without touching their markup.
 *   2. Style the rebuilt home, catalogue and categories pages (`alive-*`).
 *   3. Tint the book page's opening by its first category.
 *
 * Every colour lives in the :root block below and nowhere else. Geometry is
 * written with logical properties so `dir="rtl"` (Persian) lays out mirrored;
 * the only physical offsets are the hero's hotspots, which are fractions of the
 * printed page and must NOT mirror.
 *
 * Font families are set with longhand properties, never the `font:` shorthand:
 * the shorthand resets font-family and would put Persian text into a Latin-only
 * face (see the body.locale-fa rules in storefront-redesign.css).
 */

:root {
  --gk2-paper: #fdfbf5;
  --gk2-paper-2: #f3eee2;
  --gk2-ink: #22304a;
  --gk2-ink-soft: #5b6578;
  --gk2-line: #e3ddd0;
  --gk2-sun: #f7c948;
  --gk2-sun-deep: #e2ac1f;
  --gk2-sky: #8fc7ea;
  --gk2-leaf: #7fb88f;
  --gk2-berry: #e2607a;
  --gk2-mint: #bfe0d6;
  --gk2-coral: #d95d45;
  --gk2-night: #1c2540;
  --gk2-white: #ffffff;

  /* THE SERVICE LEVELS, in the order the region's registry declares them.
     Three PACKAGES, not three weights of one thing, so each carries its own
     colour rather than a rung on a ladder of the same hue — which is what the
     band used to be (mint, sky, sun), and on a shop whose palette is one
     colour that is three cards a reader cannot tell apart.

     A role, not a literal per surface: the colour has to mean the same level
     in all three places a level is shown — the home page's band, the order
     form's chooser and the price table's columns — or it says nothing at all.
     A shop with four levels gets the hairline for the fourth, which is the
     same default every [data-cat] takes. */
  --gk2-level-1: var(--gk2-sky);
  --gk2-level-2: var(--gk2-leaf);
  --gk2-level-3: var(--gk2-berry);

  /* rgb triplets for the few places that need an alpha */
  --gk2-ink-rgb: 34 48 74;
  --gk2-sun-rgb: 247 201 72;
  /* THE HIGHLIGHT: the ring round the character who is speaking, the brackets
     that say the camera has found the page, the bars that say it is being read
     aloud. A role of its own, because it is the one colour on the shop that is
     drawn ON THE ARTWORK — everything else the accent paints (a button, a rule,
     a link underline) sits on paper. Defaulting to the accent by var(), so a
     shop that does not re-point it renders byte for byte as before and the two
     cannot fall out of step by somebody editing one literal. */
  --gk2-glow: var(--gk2-sun);
  --gk2-glow-rgb: var(--gk2-sun-rgb);

  /* THE VIEWER: the one panel on the shop that goes DARK, so a printed page
     shown on it reads as lit. It is the book page's "look inside" reader, and
     nothing else — the two other dark surfaces carrying this colour
     (.story-scroll__backdrop, .atelier-cinema-hero__overlay) belong to layouts
     this layer replaced and are on no page the shop serves.

     It was written out as `linear-gradient(180deg, #1f4b57, #17383f)` inside
     storefront-redesign.css: two literals of the retired TEAL palette, in a
     rule no theme could reach, so the Iranian shop showed a dark green frame
     round every sample page under a blue-and-cream masthead. Same fault, and
     the same fix, as --gk2-paper-rgb. These values ARE those literals, so this
     shop renders byte for byte as before. */
  --gk2-viewer: #1f4b57;
  --gk2-viewer-deep: #17383f;
  /* Its own shadow, which needs an alpha and therefore a triplet. */
  --gk2-viewer-rgb: 23 47 55;
  /* The paper, for the masthead's translucent blur and for type set on the
     dark band. It was written out as `rgb(253 251 245 / …)` in six rules —
     the same colour as --gk2-paper, in the one form a var() cannot take an
     alpha through — which made the masthead the only surface on the shop a
     palette could not re-point. Same value, so nothing moves. */
  --gk2-paper-rgb: 253 251 245;

  --gk2-ledge: 0 1px 0 var(--gk2-line), 0 14px 30px -18px rgb(var(--gk2-ink-rgb) / 0.35);
  --gk2-float: 0 22px 40px -20px rgb(var(--gk2-ink-rgb) / 0.45);
  --gk2-ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* --- the shared tokens every older layer reads --- */
  --atelier-serif: "Young Serif", Georgia, "Times New Roman", serif;
  --font-serif: "Young Serif", Georgia, "Times New Roman", serif;
  --gk-paper: var(--gk2-paper);
  --gk-paper-strong: var(--gk2-paper-2);
  --gk-ink: var(--gk2-ink);
  --gk-ink-muted: var(--gk2-ink-soft);
  --gk-line: var(--gk2-line);
  --gk-tile: var(--gk2-paper-2);
  --gk-yellow: var(--gk2-sun);
  --gk-blue: var(--gk2-sky);
  --atelier-paper: var(--gk2-paper);
  --atelier-ink: var(--gk2-ink);
  --atelier-muted: var(--gk2-ink-soft);
  /* Read by the price lines with a `#8a7c6c` fallback and declared nowhere,
     so that warm grey is what has always rendered. Declared here at exactly
     that value: nothing moves, and a theme now has something to re-point. */
  --atelier-ink-soft: #8a7c6c;
  --atelier-border: var(--gk2-line);
  --atelier-brand: var(--gk2-ink);
  --atelier-brand-hover: var(--gk2-night);
  --atelier-brand-dark: var(--gk2-night);
  --atelier-gold: var(--gk2-sun);
  --color-primary: var(--gk2-ink);
  --color-primary-dark: var(--gk2-night);
  --color-accent: var(--gk2-sun);
}

/* Persian takes the Persian face EVERYWHERE, by re-pointing the tokens rather
 * than by listing selectors. Every face this shop ships but Vazirmatn is
 * Latin-only, so a rule that names `--atelier-serif` or `--atelier-sans` on a
 * Persian page asks for a font with no Arabic glyphs in it and the browser
 * substitutes whatever it likes — which is how the catalogue card's story name
 * ("با نام …"), the book page's price and the step numbers came out in a
 * different typeface from the sentence around them. The per-selector
 * `body.locale-fa` rules below are now belt and braces: they set the same face.
 * `style.css` already does exactly this for `--font-serif`.
 */
body.locale-fa {
  --atelier-persian: "Vazirmatn", system-ui, sans-serif;
  --atelier-serif: var(--atelier-persian);
  --atelier-sans: var(--atelier-persian);
  --font-serif: var(--atelier-persian);
  --font-sans: var(--atelier-persian);
}

html {
  scroll-behavior: smooth;
}

[id] {
  scroll-margin-top: 80px;
}

body {
  background: var(--gk2-paper);
  color: var(--gk2-ink);
}

h1, h2, h3 {
  font-family: var(--atelier-serif);
  font-weight: 400;
  letter-spacing: -0.015em;
  color: var(--gk2-ink);
}

body.locale-fa h1,
body.locale-fa h2,
body.locale-fa h3 {
  font-family: var(--atelier-persian);
  font-weight: 700;
  letter-spacing: 0;
}

/* ----------------------------------------------------------------- buttons --- */

.btn {
  border-radius: 999px;
  font-weight: 700;
  transition: background-color 160ms ease, color 160ms ease, border-color 160ms ease, transform 160ms var(--gk2-ease);
}

.btn--primary,
.btn--primary:hover,
.btn--primary:focus-visible,
.button--primary {
  background: var(--gk2-sun);
  border-color: var(--gk2-sun);
  color: var(--gk2-ink);
}

.btn--primary:hover,
.btn--primary:focus-visible {
  background: var(--gk2-sun-deep);
  border-color: var(--gk2-sun-deep);
}

.btn--outline,
.btn--outline:hover,
.btn--outline:focus-visible {
  background: transparent;
  border: 2px solid var(--gk2-ink);
  color: var(--gk2-ink);
}

.btn--outline:hover,
.btn--outline:focus-visible {
  background: var(--gk2-ink);
  color: var(--gk2-paper);
}

.btn--ink,
.btn--ink:hover,
.btn--ink:focus-visible {
  background: var(--gk2-ink);
  border-color: var(--gk2-ink);
  color: var(--gk2-paper);
}

.btn--ink:hover,
.btn--ink:focus-visible {
  background: var(--gk2-night);
}

.btn:active {
  transform: translateY(1px);
}

.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn--lg {
  padding: 15px 30px;
  font-size: 1.05rem;
}

a:focus-visible,
button:focus-visible,
summary:focus-visible,
select:focus-visible {
  outline: 2px solid var(--gk2-ink);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------- masthead --- */

.navbar--atelier {
  background: rgb(var(--gk2-paper-rgb) / 0.92);
  border-bottom: 1px solid var(--gk2-line);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.nav-logo--atelier .logo-text {
  font-family: var(--atelier-serif);
  font-weight: 400;
  font-size: 1.45rem;
  letter-spacing: -0.01em;
  color: var(--gk2-ink);
}

body.locale-fa .nav-logo--atelier .logo-text {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.nav-menu--atelier .nav-link {
  color: var(--gk2-ink);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0;
}

.nav-menu--atelier .nav-link::after {
  background: var(--gk2-ink);
  bottom: -6px;
}

.nav-menu--atelier .nav-link--quiet,
.nav-menu--atelier .nav-link--logout {
  color: var(--gk2-ink-soft);
}

.nav-menu--atelier .nav-link--cart {
  color: var(--gk2-ink);
}

.nav-menu--atelier .nav-link--cart::after {
  display: none;
}

.nav-menu--atelier .nav-cart__badge {
  background: var(--gk2-sun-deep, #c45c26);
  color: var(--gk2-ink, #1a1a1a);
}

.nav-menu--atelier .nav-link--cta,
.nav-menu--atelier .nav-link--cta:hover,
.nav-menu--atelier .nav-link--cta:focus-visible {
  padding: 9px 18px;
  border-radius: 999px;
  background: var(--gk2-sun);
  color: var(--gk2-ink);
  font-weight: 700;
  opacity: 1;
}

.nav-menu--atelier .nav-link--cta:hover,
.nav-menu--atelier .nav-link--cta:focus-visible {
  background: var(--gk2-sun-deep);
}

.nav-menu--atelier .nav-link--cta::before,
.nav-menu--atelier .nav-link--cta::after,
body.is-rtl .nav-menu--atelier .nav-link--cta::after {
  content: none;
}

body.nav-compact .nav-menu--atelier {
  background: var(--gk2-paper);
  border-color: var(--gk2-line);
  box-shadow: var(--gk2-float);
}

body.nav-compact .nav-menu--atelier .nav-link--cta {
  margin-top: 8px;
  justify-content: center;
}

/* Instagram and Bale. The picture is the thing you press; the name
   lives on the link. They sit in the footer and on the contact page. */
.social-links {
  display: flex;
  align-items: center;
  gap: 8px;
}

.footer .social-links,
.nav-menu .social-links {
  flex-wrap: nowrap;
}

.social-links a,
.footer .social-links a,
.footer-section .social-links a {
  display: inline-flex;
  flex: 0 0 36px;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 10px;
  line-height: 0;
  text-decoration: none;
  opacity: 1;
}

.social-links img {
  display: block;
  width: 28px;
  height: 28px;
}

.social-links a:hover,
.social-links a:focus-visible {
  text-decoration: none;
  opacity: 1;
  transform: translateY(-1px);
}

.social-links a:focus-visible {
  outline: 2px solid var(--gk2-ink);
  outline-offset: 3px;
}

body.nav-compact .social-links--nav {
  padding: 6px 12px;
}

.social-links--page {
  gap: 12px;
}

.social-links--page a {
  flex-basis: 52px;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: var(--gk2-white);
  border: 1px solid var(--gk2-line);
}

.social-links--page img {
  width: 36px;
  height: 36px;
}

.contact-social {
  margin-top: clamp(8px, 2vw, 16px);
}

.contact-about {
  margin-top: clamp(40px, 6vw, 72px);
}

.contact-about > h2 {
  margin: 0 0 10px;
  font-family: var(--atelier-serif);
  font-size: clamp(1.6rem, 3vw, 2.15rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--gk2-ink);
}

body.locale-fa .contact-about > h2,
body.locale-fa .contact-about h3 {
  font-family: var(--atelier-persian);
}

.contact-about > p {
  max-width: 68ch;
  margin: 0;
  color: var(--gk2-ink);
  font-size: 1.05rem;
  line-height: 1.65;
}

.contact-about .page-grid__item h3 {
  margin: 0 0 8px;
  font-family: var(--atelier-serif);
  font-size: 1.1rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--gk2-ink);
}

.lang-switch__select,
.lang-switch__label {
  color: var(--gk2-ink-soft);
}

/* ------------------------------------------------------------------ footer --- */

.footer {
  background: var(--gk2-paper-2);
  color: var(--gk2-ink);
  border-top: 1px solid var(--gk2-line);
}

.footer h3 {
  font-family: var(--atelier-serif);
  font-size: 1.05rem;
}

.footer h3.footer-name {
  margin: 0 0 8px;
  font-size: 1.35rem;
}

body.locale-fa .footer h3 {
  font-family: var(--atelier-persian);
}

.footer a,
.footer p,
.footer .footer-email-link,
.footer .footer-link-button {
  color: var(--gk2-ink);
}

.footer a,
.footer .footer-email-link,
.footer .footer-link-button {
  opacity: 0.78;
}

.footer a:hover,
.footer .footer-email-link:hover,
.footer .footer-link-button:hover {
  opacity: 1;
  text-decoration: underline;
}

.footer .social-links a,
.footer .social-links a:hover {
  opacity: 1;
  text-decoration: none;
}

.footer-links + .social-links {
  margin-top: 14px;
}

.footer-container--ir {
  grid-template-columns:
    minmax(180px, 1.2fr)
    minmax(220px, 1.4fr)
    minmax(150px, 0.95fr)
    minmax(150px, 0.95fr)
    minmax(120px, 0.8fr);
  align-items: start;
}

.footer-container--ir .footer-section--brand-mark,
.footer-container--ir .footer-section--brand-copy,
.footer-container--ir [data-trust-seal],
.footer-container--ir .footer-section:has(.footer-seal) {
  min-width: 0;
}

.footer-container--ir .footer-section--brand-mark {
  display: flex;
  align-items: flex-start;
}

.footer-container--ir .footer-section--brand-copy p:first-of-type {
  margin-top: 0;
}

/* تماس and the two icons are one row. The icon used to sit on the word,
   so the word was covered and the picture could not be read. */
.footer-contact-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
}

.footer-section .footer-contact-row > a {
  display: inline;
  width: auto;
  padding: 4px 0;
}

.footer-contact-row .social-links {
  margin-top: 0;
}

.footer-contact-icons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}

.footer-contact-icons__item,
.footer-contact-icons__item:hover,
.footer-contact-icons__item:focus-visible {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  padding: 0;
  border: 1px solid var(--gk2-line);
  border-radius: 14px;
  background: var(--gk2-white);
  color: var(--gk2-ink);
  text-decoration: none;
  opacity: 1;
}

.footer-contact-icons__item {
  transition: transform 160ms var(--gk2-ease), border-color 160ms ease, background-color 160ms ease;
}

.footer-contact-icons__item svg {
  display: block;
  width: 26px;
  height: 26px;
}

.footer-contact-icons__item:hover,
.footer-contact-icons__item:focus-visible {
  transform: translateY(-1px);
}

.footer-contact-icons__item--email {
  background: color-mix(in srgb, var(--gk2-sun) 18%, var(--gk2-white));
  color: color-mix(in srgb, var(--gk2-sun-deep) 72%, var(--gk2-ink));
}

.footer-contact-icons__item--phone {
  background: color-mix(in srgb, #8ec8ff 24%, var(--gk2-white));
  color: color-mix(in srgb, #4d7ec9 72%, var(--gk2-ink));
}

.footer-contact-icons__item--bale {
  background: color-mix(in srgb, #82ead0 26%, var(--gk2-white));
  color: color-mix(in srgb, #1e7d69 76%, var(--gk2-ink));
}

.footer-contact-icons__item--instagram {
  background: color-mix(in srgb, #f2a2c9 24%, var(--gk2-white));
  color: color-mix(in srgb, #9a3f72 74%, var(--gk2-ink));
}

.footer-contact-icons__item.footer-email-link {
  border-width: 1px;
  cursor: pointer;
}

.footer-bottom {
  border-top: 1px solid var(--gk2-line);
  color: var(--gk2-ink-soft);
}

/* The shop's short name, drawn, sitting ABOVE the heading. The heading is the
   whole name («کوالاکتاب», «Löwenbuch»); the picture letters the short form.
   Only a site that declares a brand_wordmark renders this element at all, so
   it is scoped to the element rather than branched on in the sheet.
   Sized by WIDTH here where the masthead sizes by height, because the two
   answer different questions: up there the mark has to fit a 44px bar beside a
   row of links, and down here it is the widest thing in its column and wants to
   agree with the tagline under it. So it FILLS that column, capped at half the
   file's own width — the file is written at 2x (see
   scripts/make_koala_wordmark.py) so it is sharp on a dense display and nothing
   larger is ever downloaded. The cap is what bites on a narrow viewport where
   the footer collapses to one column; at the four-column desktop width the
   column (`minmax(200px, 1fr)`) is the smaller of the two. */
.footer-brand {
  margin: 0 0 12px;
  line-height: 0;
}

.footer-brand__mark {
  display: block;
  width: 100%;
  max-width: 340px;
  height: auto;
  border-radius: 16px;
}

/* Who is behind the shop: the company's own mark, above the line naming it.
   Only a site that declares a company_logo draws the image at all, so this is
   scoped to the element rather than branched on in the sheet — gooki.de keeps
   the plain paragraph it always had. Stacked, not inline: the mark is a
   wordmark two and a bit times as wide as it is tall, and a picture that shape
   set inside a sentence reads as a broken character rather than as a logo. */
.footer-company {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin-top: 14px;
}

.footer-company__mark {
  display: block;
  /* Half the file's own width: it is written at 2x (see
     scripts/make_koala_wordmark.py) so it is sharp on a dense display and
     nothing larger is ever downloaded. */
  width: 180px;
  max-width: 100%;
  height: auto;
  border-radius: 16px;
}

@media (max-width: 980px) {
  .footer-container--ir {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer-container--ir .footer-section--brand-mark,
  .footer-container--ir .footer-section--brand-copy,
  .footer-container--ir [data-trust-seal],
  .footer-container--ir .footer-section:has(.footer-seal) {
    grid-column: 1 / -1;
  }
}

@media (max-width: 560px) {
  .footer-container--ir {
    grid-template-columns: 1fr;
  }
}

/* ================================================================== shared --- */

.alive-lead {
  max-width: 58ch;
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--gk2-ink);
}

.alive-muted {
  color: var(--gk2-ink-soft);
}

.alive-link {
  position: relative;
  display: inline-block;
  color: var(--gk2-ink);
  font-weight: 700;
  text-decoration: none;
  padding-block-end: 2px;
}

.alive-link::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 2px;
  background: var(--gk2-sun);
  transform: scaleX(0.35);
  transform-origin: inline-start;
  transition: transform 220ms var(--gk2-ease);
}

.alive-link:hover::after,
.alive-link:focus-visible::after {
  transform: scaleX(1);
}

.alive-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.alive-section {
  padding-block: clamp(56px, 8vw, 96px);
}

/* The ALTERNATING BAND — the two sections on the home page that are one step
   off the paper (the privacy promises, the family band). A role of its own
   rather than `--gk2-paper-2` directly, because that token is also the footer,
   the step panels' ground and the category rules: a shop wanting one warm band
   punctuating a cool page has to be able to say so without re-tinting the
   footer with it. Defaulting by var() to exactly what it was, so a shop that
   does not re-point it renders byte for byte as before. */
.alive-section--sheet {
  background: var(--gk2-paper-warm, var(--gk2-paper-2));
}

.alive-section--night {
  background: var(--gk2-night);
  color: var(--gk2-paper);
}

.alive-section--night h2,
.alive-section--night h3 {
  color: var(--gk2-paper);
}

.alive-head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 12px 32px;
  margin-block-end: clamp(28px, 4vw, 44px);
}

.alive-head h2 {
  margin: 0;
  max-width: 24ch;
  font-size: clamp(1.9rem, 3vw, 2.7rem);
  line-height: 1.1;
}

.alive-head p {
  margin: 8px 0 0;
  max-width: 58ch;
  color: var(--gk2-ink-soft);
  line-height: 1.6;
}

/* Category tones — one pigment per category, read off data-cat. */
[data-cat] {
  --tone: var(--gk2-line);
  --tone-ink: var(--gk2-ink);
}

[data-cat="bedtime"] {
  --tone: var(--gk2-sky);
}

[data-cat="family"] {
  --tone: var(--gk2-sun);
}

[data-cat="big-feelings"] {
  --tone: var(--gk2-berry);
}

[data-cat="first-steps"] {
  --tone: var(--gk2-leaf);
}

[data-cat="my-body"] {
  --tone: var(--gk2-mint);
}

[data-cat="learning"] {
  --tone: var(--gk2-sky);
}

[data-cat="adventure"] {
  --tone: var(--gk2-coral);
}

/* Age-band tones. A SECOND namespace on purpose: the bands are ids in their
   own registry (book_pipeline.book_ages) and putting them under [data-cat]
   would mean a band and a category that happened to agree on an id shared a
   colour. The default one line up still applies, so a band added to the
   registry and not to this file gets the hairline rather than nothing. */
[data-age] {
  --tone: var(--gk2-line);
  --tone-ink: var(--gk2-ink);
}

[data-age="1-3"] {
  --tone: var(--gk2-coral);
}

[data-age="3-5"] {
  --tone: var(--gk2-leaf);
}

[data-age="5-8"] {
  --tone: var(--gk2-sky);
}

/* Language tones, keyed by the SCRIPT rather than by the language — which is
   a property `book_pipeline.languages` already carries, and a rule rather than
   a table of eight arbitrary colours. It also says something true: the four
   tiles that share the coral are the four editions that share an alphabet, and
   a language added to the registry gets the hairline above rather than
   nothing. A third namespace for the third axis, for `[data-age]`'s reason. */
[data-lang-script] {
  --tone: var(--gk2-line);
  --tone-ink: var(--gk2-ink);
}

[data-lang-script="latin"] {
  --tone: var(--gk2-sky);
}

[data-lang-script="arabic"] {
  --tone: var(--gk2-coral);
}

[data-lang-script="hangul"] {
  --tone: var(--gk2-berry);
}

[data-lang-script="japanese"] {
  --tone: var(--gk2-leaf);
}

/* ==================================================================== hero --- */

.alive-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(40px, 6vw, 72px) clamp(48px, 7vw, 88px);
  background: var(--gk2-paper);
}

.alive-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 4.4fr) minmax(0, 7.6fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}

.alive-hero__copy h1 {
  margin: 0 0 20px;
  max-width: 14ch;
  text-wrap: balance;
  font-size: clamp(2.6rem, 5.2vw, 4.4rem);
  line-height: 1.02;
}

.alive-hero__copy .alive-lead {
  margin: 0 0 28px;
}

.alive-hero__hint {
  margin: 28px 0 0;
  max-width: 46ch;
  padding-inline-start: 14px;
  border-inline-start: 3px solid var(--gk2-sun);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--gk2-ink-soft);
}

/* --- the live page --------------------------------------------------------- */

.alive-page {
  margin: 0;
  min-width: 0;
}

/* On a wide screen the sheet runs past the column and towards the edge of the
   window, the way a book lies across a table rather than inside a box. The
   hero clips it. */
@media (min-width: 1240px) {
  .alive-page {
    margin-inline-end: -6vw;
  }
}

.alive-page__sheet {
  position: relative;
  aspect-ratio: var(--page-aspect, 2 / 1);
  width: 100%;
  border-radius: 6px;
  overflow: hidden;
  background: var(--gk2-paper-2);
  box-shadow: var(--gk2-ledge);
}

.alive-page__sheet img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The binding, where Step 10 cuts the sheet. Drawn, not implied: it is the
   one thing about a spread a screen cannot otherwise show. */
.alive-page__fold {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: rgb(var(--gk2-ink-rgb) / 0.18);
  pointer-events: none;
}

/* A hotspot is a CHARACTER's own region box, in page fractions — the figure
   lights while its line is read, and a tap asks it to speak. It is positioned
   physically (left/top), never with logical properties: the fractions are
   measured from the image's left edge in every language. A figure is taller
   than a line of type, so the corner radius is larger and the fill lighter:
   the light has to read as a glow round the figure, not a slab over it. */
.alive-page__figure {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 18px;
  background: transparent;
  cursor: pointer;
  transition: border-color 200ms ease, box-shadow 200ms ease, background-color 200ms ease;
}

.alive-page__figure:hover,
.alive-page__figure:focus-visible {
  border-color: rgb(var(--gk2-ink-rgb) / 0.35);
}

.alive-page__figure.is-live {
  border-color: var(--gk2-glow);
  background: rgb(var(--gk2-glow-rgb) / 0.12);
  box-shadow: 0 0 0 3px var(--gk2-glow), 0 0 0 6px rgb(var(--gk2-glow-rgb) / 0.35), 0 10px 24px -8px rgb(var(--gk2-ink-rgb) / 0.4);
}

.alive-page__figure:focus-visible {
  outline: 2px solid var(--gk2-ink);
  outline-offset: 2px;
}

.alive-page__caption {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "wave speaker"
    "wave line"
    "from from";
  column-gap: 14px;
  row-gap: 2px;
  margin-block-start: 16px;
  padding-inline-start: 4px;
}

.alive-wave {
  grid-area: wave;
  align-self: start;
  display: inline-flex;
  align-items: flex-end;
  gap: 3px;
  height: 22px;
  margin-block-start: 3px;
}

.alive-wave i {
  display: block;
  width: 4px;
  height: 100%;
  border-radius: 2px;
  /* Part of the highlight, not of the accent: these bars say the SAME thing
     the ring round the speaker says, one element over, and two colours saying
     one thing reads as two states. */
  background: var(--gk2-glow);
  transform: scaleY(0.25);
  transform-origin: bottom;
}

.is-playing .alive-wave i {
  animation: alive-wave 900ms ease-in-out infinite;
}

.is-playing .alive-wave i:nth-child(2) { animation-delay: 120ms; }
.is-playing .alive-wave i:nth-child(3) { animation-delay: 240ms; }
.is-playing .alive-wave i:nth-child(4) { animation-delay: 360ms; }
.is-playing .alive-wave i:nth-child(5) { animation-delay: 480ms; }

@keyframes alive-wave {
  0%, 100% { transform: scaleY(0.25); }
  50% { transform: scaleY(1); }
}

.alive-page__speaker {
  grid-area: speaker;
  font-family: var(--atelier-serif);
  font-size: 1.1rem;
  line-height: 1.3;
}

body.locale-fa .alive-page__speaker {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-page__speaker::before {
  content: attr(data-label) " · ";
  font-family: var(--atelier-sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--gk2-ink-soft);
}

body.locale-fa .alive-page__speaker::before {
  font-family: var(--atelier-persian);
}

.alive-page__line {
  grid-area: line;
  min-height: 2.9em;
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.45;
  color: var(--gk2-ink);
}

.alive-page__from {
  grid-area: from;
  margin-block-start: 8px;
  font-size: 0.85rem;
  color: var(--gk2-ink-soft);
}

.alive-page__from a {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: var(--gk2-sun);
  text-underline-offset: 3px;
}

.alive-page__from a:hover {
  color: var(--gk2-ink);
}

/* The load sequence — one orchestrated moment, then nothing moves on its own. */
@media (prefers-reduced-motion: no-preference) {
  .alive-hero__copy > * {
    animation: alive-settle 700ms var(--gk2-ease) both;
  }

  .alive-hero__copy > :nth-child(2) { animation-delay: 90ms; }
  .alive-hero__copy > :nth-child(3) { animation-delay: 180ms; }
  .alive-hero__copy > :nth-child(4) { animation-delay: 270ms; }

  .alive-page {
    animation: alive-slide 900ms var(--gk2-ease) 200ms both;
  }
}

@keyframes alive-settle {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes alive-slide {
  from { opacity: 0; transform: translateX(24px); }
  to { opacity: 1; transform: none; }
}

[dir="rtl"] .alive-page {
  animation-name: alive-slide-rtl;
}

@keyframes alive-slide-rtl {
  from { opacity: 0; transform: translateX(-24px); }
  to { opacity: 1; transform: none; }
}

/* =================================================================== shelf --- */

.alive-shelf {
  overflow: hidden;
  padding-block: clamp(48px, 6vw, 80px) 0;
  background: var(--gk2-paper-2);
}

.alive-shelf__track {
  position: relative;
  margin-block-start: 8px;
  padding-block: 12px 0;
}

.alive-shelf__row {
  display: flex;
  gap: 22px;
  width: max-content;
  padding-inline: 22px;
}

.alive-shelf__row--drift {
  animation: alive-drift 80s linear infinite;
}

[dir="rtl"] .alive-shelf__row--drift {
  animation-name: alive-drift-rtl;
}

.alive-shelf__track:hover .alive-shelf__row--drift,
.alive-shelf__track:focus-within .alive-shelf__row--drift {
  animation-play-state: paused;
}

@keyframes alive-drift {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes alive-drift-rtl {
  from { transform: translateX(0); }
  to { transform: translateX(50%); }
}

.alive-shelf__book {
  flex: 0 0 auto;
  width: clamp(120px, 15vw, 180px);
  aspect-ratio: 1;
  border-radius: 4px 8px 8px 4px;
  overflow: hidden;
  background: var(--gk2-white);
  box-shadow: var(--gk2-ledge);
  transition: transform 260ms var(--gk2-ease), box-shadow 260ms ease;
}

.alive-shelf__book img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.alive-shelf__book:hover,
.alive-shelf__book:focus-visible {
  transform: translateY(-8px);
  box-shadow: var(--gk2-float);
}

/* The ledge the books stand on. */
.alive-shelf__ledge {
  height: 14px;
  margin-block-start: 0;
  border-top: 2px solid var(--gk2-line);
  background: linear-gradient(180deg, rgb(var(--gk2-ink-rgb) / 0.08), transparent);
}

@media (prefers-reduced-motion: reduce) {
  .alive-shelf__row--drift {
    animation: none;
  }

  .alive-shelf__track {
    overflow-x: auto;
  }
}

/* =================================================================== steps --- */

.alive-steps__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(18px, 2.5vw, 28px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: alive-step;
}

.alive-step {
  counter-increment: alive-step;
  min-width: 0;
}

/* Four square panels — the book's own 17 x 17 module. */
.alive-step__panel {
  position: relative;
  aspect-ratio: 1;
  border-radius: 14px;
  overflow: hidden;
  background: var(--tone, var(--gk2-paper-2));
}

.alive-step__panel::before {
  content: counter(alive-step);
  position: absolute;
  inset-block-start: 12px;
  inset-inline-start: 14px;
  z-index: 2;
  font-family: var(--atelier-serif);
  font-size: 1.3rem;
  line-height: 1;
  color: var(--gk2-ink);
}

.alive-step h3 {
  margin: 16px 0 6px;
  font-size: 1.25rem;
  line-height: 1.2;
}

.alive-step p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--gk2-ink-soft);
}

.alive-step__panel > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 88% 55%;
}

/* 1 — three covers, fanned */
.alive-fan {
  position: absolute;
  inset: 0;
}

.alive-fan img {
  position: absolute;
  width: 46%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  box-shadow: var(--gk2-ledge);
  background: var(--gk2-white);
}

.alive-fan img:nth-child(1) { left: 12%; top: 36%; transform: rotate(-8deg); }
.alive-fan img:nth-child(2) { left: 30%; top: 26%; transform: rotate(2deg); z-index: 1; }
.alive-fan img:nth-child(3) { left: 48%; top: 38%; transform: rotate(9deg); }

/* 2 — photo becomes character */
.alive-morph {
  position: absolute;
  inset: 0;
}

.alive-morph img {
  position: absolute;
  width: 54%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 6px;
  box-shadow: var(--gk2-ledge);
  background: var(--gk2-white);
}

.alive-morph img:nth-child(1) { left: 8%; top: 18%; transform: rotate(-4deg); }
.alive-morph img:nth-child(2) { right: 8%; bottom: 12%; transform: rotate(3deg); z-index: 1; }

/* 3 — three voices */
.alive-voices {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  gap: 14px;
  padding: 22% 14% 14%;
}

.alive-voices__row {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 10px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--gk2-ink);
}

.alive-voices__bars {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 18px;
}

.alive-voices__bars i {
  flex: 1;
  height: calc(20% + var(--h) * 80%);
  border-radius: 2px;
  background: rgb(var(--gk2-ink-rgb) / 0.55);
}

/* --- the family strip ------------------------------------------------------- */

.alive-family {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.5vw, 28px);
}

.alive-family figure {
  margin: 0;
  min-width: 0;
}

.alive-family__frame {
  aspect-ratio: 1;
  border-radius: 14px;
  overflow: hidden;
  background: var(--gk2-paper-2);
  box-shadow: var(--gk2-ledge);
}

.alive-family__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.alive-family figcaption {
  margin-block-start: 14px;
}

.alive-family figcaption strong {
  display: block;
  font-family: var(--atelier-serif);
  font-weight: 400;
  font-size: 1.15rem;
  margin-block-end: 4px;
}

body.locale-fa .alive-family figcaption strong {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-family figcaption span {
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--gk2-ink-soft);
}

/* ================================================================ tiles --- */

.alive-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 22px);
}

.alive-tile {
  position: relative;
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  gap: 8px;
  min-height: 240px;
  padding: 22px 22px 18px;
  border-radius: 16px;
  background: var(--gk2-paper);
  border: 1px solid var(--gk2-line);
  color: var(--gk2-ink);
  text-decoration: none;
  overflow: hidden;
  transition: transform 260ms var(--gk2-ease), border-color 200ms ease;
}

.alive-tile::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 6px;
  background: var(--tone);
}

.alive-tile:hover,
.alive-tile:focus-visible {
  transform: translateY(-4px);
  border-color: var(--tone);
}

.alive-tiles .alive-tile:first-child {
  grid-column: span 2;
}

/* An axis with few, equal members. The wide first tile is what gives seven
   topics a front page; over three age bands it makes one band twice the size
   of the other two for no reason a reader can name. */
.alive-tiles--even .alive-tile:first-child {
  grid-column: auto;
}

/* --- the browse page's three axes --------------------------------------- */

.browse-axis {
  margin-block-start: clamp(36px, 5vw, 56px);
}

.browse-axis__head {
  margin-block-end: clamp(14px, 2vw, 20px);
}

.browse-axis__head h2 {
  margin: 0 0 4px;
  font-family: var(--atelier-serif);
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--gk2-ink);
}

.browse-axis__head p {
  margin: 0;
  max-width: 62ch;
  color: var(--gk2-ink-soft);
}

.alive-tile__icon {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--tone);
  color: var(--gk2-ink);
}

.alive-tile__icon .cat-icon {
  width: 20px;
  height: 20px;
}

/* A language tile's mark is a letter out of the script the book will be
   PRINTED in — ف, 한, 日 — so the tile shows what the page is going to look
   like rather than naming it twice. It is set in the face the storefront
   already loads for that script, and it is decoration: the tile's heading is
   the language's name in the customer's own words. */
.alive-tile__glyph {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

.alive-tile h2,
.alive-tile h3 {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.15;
}

.alive-tile p {
  margin: 0;
  max-width: 40ch;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--gk2-ink-soft);
}

.alive-tile__foot {
  /* The LAST row, named from the end, rather than wherever the children happen
     to fall. The tile is four explicit rows — icon, heading, blurb, foot — and
     a tile with no blurb has only three children, so the foot landed in the
     `1fr` row and sat a row-gap short of the bottom while its neighbours did
     not. Visible the day an axis had a member with nothing to say about
     itself: a language named in its own shop, whose endonym IS its label. */
  grid-row: -2 / -1;
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 12px;
  margin-block-start: 8px;
}

.alive-tile__count {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--gk2-ink-soft);
}

.alive-tile__covers {
  display: flex;
}

.alive-tile__covers img {
  width: 52px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 4px;
  border: 2px solid var(--gk2-paper);
  background: var(--gk2-white);
  box-shadow: var(--gk2-ledge);
  transition: transform 260ms var(--gk2-ease);
}

.alive-tile__covers img + img {
  margin-inline-start: -14px;
}

.alive-tile:hover .alive-tile__covers img:nth-child(1) { transform: translateY(-3px) rotate(-6deg); }
.alive-tile:hover .alive-tile__covers img:nth-child(2) { transform: translateY(-6px); }
.alive-tile:hover .alive-tile__covers img:nth-child(3) { transform: translateY(-3px) rotate(6deg); }

/* ============================================================== arrives --- */

.alive-arrives {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
}

.alive-arrives h2 {
  margin: 0 0 14px;
  font-size: clamp(1.9rem, 3vw, 2.7rem);
  line-height: 1.1;
}

.alive-arrives p {
  max-width: 52ch;
  line-height: 1.65;
  color: rgb(var(--gk2-paper-rgb) / 0.82);
}

.alive-arrives .btn {
  margin-block-start: 8px;
}

/* The facts, set like a colophon. */
.alive-colophon {
  margin: 0;
  padding: 26px 28px;
  border: 1px solid rgb(var(--gk2-paper-rgb) / 0.22);
  border-radius: 14px;
}

.alive-colophon div {
  display: grid;
  grid-template-columns: minmax(0, 9ch) 1fr;
  gap: 16px;
  padding-block: 12px;
  border-top: 1px dashed rgb(var(--gk2-paper-rgb) / 0.22);
}

.alive-colophon div:first-child {
  border-top: 0;
  padding-block-start: 0;
}

.alive-colophon dt {
  font-size: 0.85rem;
  font-weight: 600;
  color: rgb(var(--gk2-paper-rgb) / 0.7);
}

.alive-colophon dd {
  margin: 0;
  font-family: var(--atelier-serif);
  font-size: 1.15rem;
  line-height: 1.3;
}

body.locale-fa .alive-colophon dd {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-safety {
  margin-block-start: 28px;
  padding-block-start: 22px;
  border-top: 1px solid rgb(var(--gk2-paper-rgb) / 0.22);
}

.alive-safety h3 {
  margin: 0 0 8px;
  font-size: 1.25rem;
}

.alive-safety p {
  margin: 0;
  font-size: 0.95rem;
}

/* ================================================================== faq --- */

.alive-faq {
  max-width: 760px;
}

.alive-faq details {
  border-top: 1px solid var(--gk2-line);
}

.alive-faq details:last-child {
  border-bottom: 1px solid var(--gk2-line);
}

.alive-faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 4px;
  cursor: pointer;
  list-style: none;
  font-family: var(--atelier-serif);
  font-size: 1.15rem;
  line-height: 1.3;
}

body.locale-fa .alive-faq summary {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-faq summary::-webkit-details-marker {
  display: none;
}

.alive-faq summary::after {
  content: "+";
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--gk2-sun);
  color: var(--gk2-ink);
  font-family: var(--atelier-sans);
  font-weight: 700;
  transition: transform 220ms var(--gk2-ease);
}

.alive-faq details[open] summary::after {
  transform: rotate(45deg);
}

.alive-faq p {
  margin: 0;
  padding: 0 4px 20px;
  max-width: 62ch;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

/* ================================================================== end --- */

/* The closing band: the single biggest area of colour on the page, and the
   one that asks for the sale. `--gk2-end` is a role of its own rather than the
   accent, because the accent is what every BUTTON on the page is painted with
   — including the two standing in this band — and a band the same colour as
   the button inside it has nothing for that button to stand on. It defaults by
   var() to the accent, so a shop that does not re-point it is byte-identical
   and the two cannot drift by somebody editing one literal. Whatever is put
   here has to carry `--gk2-ink` at 4.5:1: the band holds a paragraph and a
   link, not only display type. */
.alive-end {
  background: var(--gk2-end, var(--gk2-sun));
  color: var(--gk2-ink);
  text-align: center;
  padding-block: clamp(64px, 10vw, 120px);
}

.alive-end h2 {
  margin: 0;
  font-size: clamp(3rem, 8vw, 6.5rem);
  line-height: 1;
}

.alive-end p {
  margin: 12px 0 28px;
  font-size: clamp(1.1rem, 2vw, 1.4rem);
}

.alive-end .alive-actions {
  justify-content: center;
}

.alive-end__again {
  display: inline-block;
  margin-block-start: 36px;
  color: var(--gk2-ink);
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* ============================================================== catalogue --- */

.alive-catalog {
  padding-block: clamp(40px, 6vw, 72px) clamp(56px, 8vw, 96px);
}

.alive-catalog__head {
  display: grid;
  gap: 10px;
  margin-block-end: 28px;
}

.alive-catalog__head h1 {
  margin: 0;
  font-size: clamp(2.2rem, 4.5vw, 3.6rem);
  line-height: 1.04;
  max-width: 16ch;
}

.alive-catalog__head p {
  margin: 0;
  max-width: 58ch;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

.alive-catalog__count {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--gk2-ink-soft);
}

/* --- the filter, coloured by its own category --------------------------- */

.alive-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-block-end: clamp(28px, 4vw, 44px);
}

/* A SECOND and third chip row under the topics — age, and the language the
   copy is printed in. Tighter than the topic row and labelled, because three
   unlabelled rows of chips is a wall: the reader has to be told which question
   each row answers. */
.alive-chips--axis {
  align-items: center;
  margin-block-end: clamp(16px, 2.4vw, 24px);
}

.alive-chips__label {
  margin-inline-end: 4px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gk2-ink-soft);
}

.alive-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--gk2-line);
  border-radius: 999px;
  background: var(--gk2-paper);
  color: var(--gk2-ink);
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
  transition: background-color 160ms ease, border-color 160ms ease, transform 160ms var(--gk2-ease);
}

.alive-chip::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--tone, var(--gk2-ink));
}

/* The "all" chip stands for no category, so its dot has no tone to take and was
   painted in the ink — which is also what an active chip is FILLED with, so on
   the selected chip it was a navy dot on navy and simply disappeared. It follows
   the chip's own text colour instead: ink on paper while it is resting, paper on
   ink once it is chosen. Every other chip's dot is its category's own pastel
   (sky, sun, berry, leaf, mint, coral) and reads against both. */
.alive-chip--all::before {
  background: currentColor;
}

.alive-chip:hover,
.alive-chip:focus-visible {
  border-color: var(--gk2-ink);
  transform: translateY(-1px);
}

.alive-chip.is-active {
  background: var(--gk2-ink);
  border-color: var(--gk2-ink);
  color: var(--gk2-paper);
}

.alive-chip .cat-icon {
  display: none;
}

.alive-chip__count {
  font-weight: 600;
  opacity: 0.6;
}

/* --- the shelf grid ------------------------------------------------------- */

.alive-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 44px) clamp(18px, 3vw, 32px);
}

.alive-book {
  position: relative;
  display: grid;
  /* The outer grid gives every card in a row the tallest card's height, and a
     grid's rows stretch into that by default — so a card with less text handed
     its spare height to the STAGE row and its cover stopped being square (363
     wide, up to 386 tall, next to a neighbour at 363). Cover and ledge are
     sized to their content; the words take whatever is left. */
  grid-template-rows: auto auto 1fr;
  gap: 0;
  min-width: 0;
}

.alive-book__stage {
  position: relative;
  aspect-ratio: 1;
  isolation: isolate;
}

.alive-book__cover {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 4px 8px 8px 4px;
  overflow: hidden;
  background: var(--gk2-white);
  box-shadow: var(--gk2-ledge);
  transition: transform 300ms var(--gk2-ease), box-shadow 300ms ease;
}

.alive-book__cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The first spread, hidden behind the cover until the cover lifts. */
.alive-book__peek {
  position: absolute;
  inset-inline-start: 4%;
  inset-block-start: 40%;
  width: 92%;
  aspect-ratio: 2 / 1;
  border-radius: 4px;
  overflow: hidden;
  background: var(--gk2-paper-2);
  box-shadow: var(--gk2-ledge);
  opacity: 0;
  transform: translateY(6px) scale(0.96);
  transition: opacity 260ms ease, transform 300ms var(--gk2-ease);
}

.alive-book__peek img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.alive-book__peek span {
  position: absolute;
  inset-inline-start: 8px;
  inset-block-end: 8px;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--gk2-ink);
  color: var(--gk2-paper);
  font-size: 0.7rem;
  font-weight: 700;
}

@media (hover: hover) {
  .alive-book:hover .alive-book__stage,
  .alive-book:focus-within .alive-book__stage {
    z-index: 3;
  }

  .alive-book:hover .alive-book__cover,
  .alive-book:focus-within .alive-book__cover {
    transform: translate(-4%, -14%) rotate(-5deg) scale(0.6);
    transform-origin: top left;
    box-shadow: var(--gk2-float);
  }

  [dir="rtl"] .alive-book:hover .alive-book__cover,
  [dir="rtl"] .alive-book:focus-within .alive-book__cover {
    transform: translate(4%, -14%) rotate(5deg) scale(0.6);
    transform-origin: top right;
  }

  .alive-book:hover .alive-book__peek,
  .alive-book:focus-within .alive-book__peek {
    opacity: 1;
    transform: none;
  }
}

.alive-book__ledge {
  height: 10px;
  margin-inline: -4px;
  border-top: 2px solid var(--gk2-line);
  background: linear-gradient(180deg, rgb(var(--gk2-ink-rgb) / 0.07), transparent);
}

.alive-book__body {
  display: flex;
  flex-direction: column;
  padding-block-start: 12px;
}

.alive-book__kicker {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin: 0 0 8px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--gk2-ink-soft);
}

.alive-book__kicker a {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--gk2-ink);
  text-decoration: none;
}

.alive-book__kicker a::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--tone, var(--gk2-line));
}

.alive-book__kicker a:hover {
  text-decoration: underline;
}

.alive-book__title {
  margin: 0 0 6px;
  font-size: 1.3rem;
  line-height: 1.2;
}

.alive-book__title a {
  color: inherit;
  text-decoration: none;
}

/* One link over the whole tile: the title's link stretches, so cover, words
   and price are a single target. The category links sit above it (z-index). */
.alive-book__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.alive-book__title a:focus-visible {
  outline: none;
}

.alive-book:focus-within .alive-book__title a {
  text-decoration: underline;
  text-decoration-color: var(--gk2-sun);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.alive-book__story {
  margin: 0 0 6px;
  font-size: 0.9rem;
  color: var(--gk2-ink-soft);
}

.alive-book__story em {
  font-style: normal;
  color: var(--gk2-ink);
}

.alive-book__blurb {
  margin: 0 0 8px;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--gk2-ink-soft);
}

.alive-book__spec {
  margin: 0 0 12px;
  font-size: 0.82rem;
  color: var(--gk2-ink-soft);
}

.alive-book__buy {
  /* The price line sits on the card's floor, so a row of cards reads as one
     shelf: its neighbours' blurbs differ in length, and the buy line would
     otherwise land at a different height on each. */
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: auto 0 0;
}

.alive-book__price {
  font-family: var(--atelier-serif);
  font-size: 1.2rem;
}

body.locale-fa .alive-book__price {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-book__cta {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--gk2-ink);
  border-bottom: 2px solid var(--gk2-sun);
}

/* `.alive-book` is a grid, and an author `display` beats the UA stylesheet's
   `[hidden] { display: none }` — so without this the shelf's filter hides
   nothing at all. The shelf renders every card and `hidden` is what the filter
   IS, on the server as well as in the browser. */
.alive-book[hidden] {
  display: none;
}

.alive-empty {
  grid-column: 1 / -1;
  padding: 48px 0;
  color: var(--gk2-ink-soft);
}

/* =========================================================== book page --- */

.book-page__hero {
  position: relative;
}

.alive-detail .book-page__cover-figure {
  position: relative;
  padding: clamp(16px, 3vw, 36px);
  border-radius: 18px;
  background: var(--tone, var(--gk2-paper-2));
}

.alive-detail .book-page__cover {
  border-radius: 4px 8px 8px 4px;
  box-shadow: var(--gk2-float);
}

.alive-detail .atelier-eyebrow {
  display: none;
}

.alive-detail .book-page__story-title em {
  font-family: var(--atelier-serif);
  font-style: normal;
}

/* ============================================================ responsive --- */

@media (max-width: 1100px) {
  .alive-hero__copy h1 {
    font-size: clamp(2.4rem, 4.6vw, 3.6rem);
  }
}

@media (max-width: 960px) {
  .alive-hero__grid {
    grid-template-columns: 1fr;
  }

  .alive-hero__copy h1 {
    max-width: 16ch;
  }

  .alive-steps__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .alive-arrives {
    grid-template-columns: 1fr;
  }

  .alive-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .alive-family,
  .alive-tiles {
    grid-template-columns: 1fr;
  }

  .alive-tiles .alive-tile:first-child {
    grid-column: auto;
  }

  .alive-tile {
    min-height: 0;
  }
}

@media (max-width: 480px) {
  .container {
    padding-inline: 16px;
  }

  .alive-steps__grid,
  .alive-grid {
    grid-template-columns: 1fr;
  }

  .alive-hero__copy h1 {
    font-size: 2.3rem;
  }

  .alive-page__caption {
    grid-template-columns: 1fr;
    grid-template-areas:
      "speaker"
      "line"
      "from";
  }

  .alive-wave {
    display: none;
  }

  .alive-actions .btn {
    flex: 1 1 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .alive-hero__copy > *,
  .alive-page,
  .alive-wave i {
    animation: none !important;
  }

  .alive-shelf__book,
  .alive-tile,
  .alive-book__cover,
  .alive-book__peek,
  .alive-chip,
  .btn {
    transition: none;
  }
}

/* --- price: a sale, and the figure it replaced --------------------------- */
/* A struck-through old price only means anything beside the new one, so both
   are set on one line and the old one is quiet. The badge carries the
   campaign's own name where it has one ("Spring sale"), not the word "sale",
   because a shop's own words are what a customer remembers. */
.alive-book__price-was,
.atelier-price-was {
  color: var(--atelier-ink-soft, #8a7c6c);
  font-size: 0.85em;
  font-weight: 400;
  margin-inline-end: 6px;
}

.price-tag-sale {
  display: inline-block;
  margin-inline-start: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  background: #2d6457;
  color: #fffaf3;
  font-family: var(--atelier-sans, inherit);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

body.locale-fa .price-tag-sale {
  font-family: var(--atelier-persian);
  letter-spacing: 0;
  text-transform: none;
}

/* On a catalogue card the badge sits UNDER the two figures and the delivery
   note, so it starts a line of its own: the inline gap that separated it from
   a price beside it would print as an indent. */
.alive-book__delivery + .price-tag-sale,
.alive-book__price-options + .price-tag-sale {
  margin-inline-start: 0;
  margin-top: 6px;
}

/* The code box: one line on a wide screen, stacked on a phone. */
.order-review-discount .row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.order-review-discount input[type="text"] {
  flex: 1 1 180px;
  min-width: 0;
  text-transform: uppercase;
}

.order-review-price .summary-table {
  width: 100%;
  margin-bottom: 16px;
}

/* A book the shop cannot price yet: on the shelf, quietly, with no price. */
.alive-book__unpriced {
  font-family: var(--atelier-sans, inherit);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--atelier-ink-soft, #8a7c6c);
}

/* The book's price is never the whole bill: delivery is added at checkout, so
   the figure is followed by a quiet note saying so wherever it is shown — and
   the note NAMES this shop's cheapest delivery wherever it can name one, so
   the reader can do the sum. That makes it far too long to sit beside the
   figure: it gets a line of its own everywhere it appears. A "from …" figure
   adds a second quiet line naming which choices (language / package /
   printing) can move the price. */
.alive-book__delivery,
.alive-book__price-options,
.atelier-price-delivery,
.atelier-price-options,
.atelier-price-min,
.atelier-price-checkout,
.order-review-delivery {
  color: var(--atelier-ink-soft, #8a7c6c);
  font-family: var(--atelier-sans, inherit);
  font-weight: 400;
  line-height: 1.45;
}

/* On a catalogue card the buy line is a flex row — price on the left, call to
   action on the right — so the price column is about half a card wide. Inline,
   the note pushed its own currency off the card's edge. */
.alive-book__delivery,
.alive-book__price-options {
  display: block;
  font-size: 0.75rem;
  margin: 2px 0 0;
}

/* On the book page the price row is a WRAPPING flex, so the note and the
   sentence under it each claim a whole row instead of being indented by the
   row's own gap. */
.atelier-price-delivery,
.atelier-price-options,
.atelier-price-min,
.atelier-price-checkout {
  flex: 0 0 100%;
  margin: 0;
}

/* The sentence that says what the missing part is waiting on. It is a full
   sentence, not a suffix to a figure. */
.atelier-price-checkout,
.order-review-delivery {
  display: block;
}

.order-review-delivery {
  font-size: 0.8rem;
  margin: -8px 0 12px;
}

.order-review-parcel-weight {
  margin: 0 0 12px;
  color: var(--atelier-ink-soft, #35505a);
  font-size: 0.95rem;
  line-height: 1.45;
}

/* ======================================================== service levels --- */
/* The band on the home page that says the product is sold at three levels
   (_home_service_tiers.html). It renders on a shop whose region declares
   `service_tiers` and nowhere else, so these rules are inert on gooki.de.

   Written with logical properties throughout, because the one shop that has
   levels is the Persian one and the whole band lays out mirrored. */

.alive-levels {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Flex column rather than a fixed row track: a level may render without a
   price (a currency this shop cannot quote) or without a description, and a
   track list then leaves the feature list floating in the middle of the card.
   `margin-block-start: auto` on the list is what keeps the three cards' ticks
   on one line whatever is above them. */
.alive-level {
  --level-tone: var(--gk2-line);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 24px 22px 20px;
  border-radius: 16px;
  /* The plain declaration first: a browser without color-mix keeps a white
     card and the tone is still carried by the rule and the ticks, so the three
     levels stay three colours either way. */
  background: var(--gk2-white);
  background: color-mix(in srgb, var(--level-tone) 14%, var(--gk2-white));
  border: 1px solid var(--gk2-line);
  border-color: color-mix(in srgb, var(--level-tone) 38%, var(--gk2-white));
  position: relative;
  overflow: hidden;
}

/* Each card is WASHED in its own level's colour, and carries it again on the
   rule across its top and on every tick down its list. The card used to be the
   page's own paper with a 6px rule that climbed mint -> sky -> sun: one hue in
   three strengths, which on the one shop that has levels resolved to three
   pale blues nobody could tell apart. The tone is the level's, out of
   `--gk2-level-N`, so the same colour means the same level on the order form
   and in the price table.

   It is deliberately still not a "most popular" flag: three colours say the
   three are DIFFERENT, where a badge on one says the other two are wrong. */
.alive-level:nth-child(1) { --level-tone: var(--gk2-level-1); }
.alive-level:nth-child(2) { --level-tone: var(--gk2-level-2); }
.alive-level:nth-child(3) { --level-tone: var(--gk2-level-3); }

.alive-level::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 8px;
  background: var(--level-tone);
}

.alive-level__name {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.15;
}

.alive-level__price {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
}

.alive-level__amount {
  font-family: var(--atelier-serif);
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--gk2-ink);
}

body.locale-fa .alive-level__amount {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-level__plus {
  font-size: 0.8rem;
  color: var(--gk2-ink-soft);
}

.alive-level__desc {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--gk2-ink-soft);
}

.alive-level__has {
  margin: auto 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
  align-content: start;
  border-block-start: 1px solid var(--gk2-line);
  border-block-start-color: color-mix(in srgb, var(--level-tone) 45%, var(--gk2-white));
  padding-block-start: 14px;
}

.alive-level__has li {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 10px;
  align-items: start;
  font-size: 0.9rem;
  line-height: 1.45;
}

/* Decorative: every line in this list is something the level HAS, so the tick
   carries no information of its own and is never read out. */
.alive-level__tick {
  inline-size: 18px;
  block-size: 18px;
  margin-block-start: 1px;
  border-radius: 50%;
  background: var(--level-tone, var(--gk2-leaf));
  position: relative;
}

.alive-level__tick::after {
  content: "";
  position: absolute;
  inset-block-start: 4px;
  inset-inline-start: 6px;
  inline-size: 4px;
  block-size: 8px;
  border: solid var(--gk2-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* The tick is a drawn shape, not a glyph, so it must NOT mirror with the text:
   a check mark reversed reads as a stray mark. */
[dir="rtl"] .alive-level__tick::after {
  inset-inline-start: auto;
  inset-inline-end: 6px;
}

.alive-levels__note {
  margin: clamp(18px, 3vw, 28px) 0 0;
  max-width: 68ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

@media (max-width: 960px) {
  .alive-levels {
    grid-template-columns: 1fr;
  }

  .alive-level__has {
    margin-block-start: 4px;
  }
}

/* ======================================================== print editions --- */
/* The band on the home page that says a book is printed in more than one
   edition (_home_print_editions.html). It renders on a shop whose region
   declares `print_products` and nowhere else, so these rules are inert until
   one does.

   Deliberately NOT a copy of `.alive-level`: the two bands answer different
   questions and stand one above the other, and rendered identically a reader
   would take the second for a repeat of the first. A level is a ladder — it
   climbs, and the rule across each card climbs with it — while the editions are
   alternatives at one level, so they carry no ladder and no coloured rule. What
   distinguishes them is the one that is INCLUDED in the advertised price, and
   that is the first card.

   `auto-fit` rather than a fixed three, because the number of editions is the
   shop's: gooki.de prints three, and a shop with two must not leave a hole.

   Logical properties throughout — one shop that prints several editions is the
   Persian one and the whole band lays out mirrored. */

.alive-editions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.alive-edition {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 22px 22px 20px;
  border-radius: 16px;
  background: var(--gk2-paper);
  border: 1px solid var(--gk2-line);
}

/* The edition the catalogue's price already includes. A quiet inline rule
   rather than a badge: it is the default, not a recommendation, and a badge
   over one of three alternatives reads as an upsell. */
.alive-edition--base {
  border-inline-start: 4px solid var(--gk2-mint);
}

.alive-edition__name {
  margin: 0;
  font-size: 1.2rem;
  line-height: 1.2;
}

.alive-edition__price {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
}

.alive-edition__amount {
  font-family: var(--atelier-serif);
  font-size: 1.4rem;
  line-height: 1.1;
  color: var(--gk2-ink);
}

body.locale-fa .alive-edition__amount {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.alive-edition__plus {
  font-size: 0.8rem;
  color: var(--gk2-ink-soft);
}

.alive-edition__desc {
  margin: 0;
  font-size: 0.93rem;
  line-height: 1.55;
  color: var(--gk2-ink-soft);
}

/* The printer's name, last and quietest: it is a credit, not a selling point,
   and `margin-block-start: auto` keeps it on the card's floor whatever length
   the description above it turned out to be. */
.alive-edition__maker {
  margin: auto 0 0;
  padding-block-start: 12px;
  border-block-start: 1px solid var(--gk2-line);
  font-size: 0.82rem;
  color: var(--gk2-ink-soft);
}

.alive-editions__note {
  margin: clamp(18px, 3vw, 28px) 0 0;
  max-width: 68ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

/* ============================================================ price list --- */
/* The whole price table (prices.html): rows are editions, columns are levels.
   It renders on every shop — a shop selling one edition at one level gets one
   cell — so unlike the two bands above these rules are never inert.

   Logical properties throughout: the shop that has the most to put in this
   table is the Persian one, and the whole page lays out mirrored. The one
   PHYSICAL thing is the horizontal scroll container, which is a direction the
   table overflows in rather than a side of the page.

   A real <table>, not a grid of cards: what a reader does here is compare one
   edition across the levels and one level across the editions, and that is
   exactly what a row and a column header buy them — in a screen reader as
   much as by eye. */

.price-sizes {
  margin: 12px 0 0;
  font-size: 0.95rem;
  color: var(--gk2-ink-soft);
}

/* WHICH BOOK the table is quoting. A row rather than a stacked label-over-
   field, because it reads as one sentence — "Which book? <this one>" — and
   `wrap` is what keeps that true on a phone, where the <select> takes the next
   line by itself rather than being squeezed beside its own label.

   Logical properties throughout, like the rest of this block: the shop with
   the longest book titles is the Persian one and the whole page is mirrored.
   It is deliberately the same control as the book page's own language picker
   (`.book-reader__lang`) — the same row of label, native <select> and a
   <noscript> button, and the same pill — because they ask the same shape of
   question about the same shelf, and two storefront pickers that look
   different read as two different kinds of control. */
.price-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin-block-start: clamp(18px, 2.5vw, 26px);
}

.price-picker__label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--gk2-ink);
}

/* `1 1 260px` rather than a width: a shop's longest title decides how wide
   this wants to be and the flex row is what lets it take the next line whole
   on a phone instead of being squeezed beside its own label. The cap is so a
   desktop does not draw one control across the whole measure. */
.price-picker__select {
  flex: 1 1 260px;
  max-inline-size: 460px;
  padding: 8px 14px;
  font: inherit;
  font-size: 0.95rem;
  color: var(--gk2-ink);
  background: var(--gk2-white);
  border: 1px solid var(--gk2-line);
  border-radius: 999px;
}

/* What has to be added to EVERY figure in the table, so it sits against the
   table rather than below the level cards, where it used to be and was read by
   nobody. Two sentences of different weight on one line: the "+ delivery" is
   the thing being said, and the clause after it says where the number is. */
.price-delivery {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: clamp(12px, 1.8vw, 18px) 0 0;
  max-width: 68ch;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

/* Narrow screens and five editions by three levels: the table keeps its shape
   and the page does not. `-inline` so the page itself never scrolls sideways. */
.price-table__scroll {
  margin-block-start: clamp(20px, 3vw, 32px);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.price-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 480px;
}

.price-table__caption {
  caption-side: top;
  text-align: start;
  padding-block-end: 12px;
  font-size: 0.9rem;
  color: var(--gk2-ink-soft);
}

.price-table th,
.price-table td {
  padding: 14px 16px;
  text-align: start;
  vertical-align: top;
  border-block-end: 1px solid var(--gk2-line);
}

.price-table thead th {
  font-size: 1.05rem;
  line-height: 1.2;
  border-block-end: 2px solid var(--gk2-line);
  white-space: nowrap;
}

/* One column per LEVEL, coloured the way the level is coloured everywhere
   else: the rule under the heading is that level's own tone, so a reader who
   met the three cards on the home page reads the same three here rather than
   three identical columns of figures. Column 1 is the edition, so the levels
   start at 2; a shop with one level heads its single column with the plain
   word "Price" and takes the first tone, which is harmless.

   The heading cell alone is washed. Tinting the whole column would colour the
   figures' own ground, and what this table is for is comparing figures.

   `--levels` is set by the template only above ONE column: a shop selling at a
   single level names no choice there, so it takes the plain hairline it always
   had and gooki.de's table is untouched. */
.price-table--levels thead tr:first-child th:nth-child(2) { --level-tone: var(--gk2-level-1); }
.price-table--levels thead tr:first-child th:nth-child(3) { --level-tone: var(--gk2-level-2); }
.price-table--levels thead tr:first-child th:nth-child(4) { --level-tone: var(--gk2-level-3); }

.price-table--levels thead tr:first-child th:nth-child(n + 2) {
  border-block-end-width: 3px;
  border-block-end-color: var(--level-tone, var(--gk2-line));
  background: color-mix(in srgb, var(--level-tone) 14%, transparent);
}

/* LANGUAGE as rows. Each edition is a <tbody>: a heading row spanning the
   table names it, and one quieter row per language carries the figures, so
   the packages stay the only columns. Without this class every edition is a
   single row, which is every shop but the Iranian one. */
.price-table--languages .price-table__group-head th {
  padding-block: 18px 8px;
  border-block-end: 0;
  background: color-mix(in srgb, var(--gk2-line) 30%, transparent);
}

.price-table--languages tbody th.price-table__lang {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--gk2-ink-soft);
  padding-inline-start: 28px;
  white-space: nowrap;
}

.price-table--levels thead th:nth-child(n + 2),
.price-table--levels td {
  text-align: center;
}

/* The row header is three lines of different weight — the edition, what it is
   made of, who makes it — so it is a stack rather than a run of text. */
.price-table tbody th {
  font-weight: 600;
  display: table-cell;
}

.price-table__edition {
  display: block;
  font-size: 1rem;
  line-height: 1.3;
}

.price-table__desc,
.price-table__maker {
  display: block;
  margin-block-start: 4px;
  font-weight: 400;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--gk2-ink-soft);
}

/* The edition the advertised price already includes. The same quiet inline
   rule the home page's card carries, for the same reason: it is the default,
   not a recommendation, and a badge on one of five reads as an upsell. */
.price-table__row--base th[scope="row"],
.price-table__row--base th[scope="colgroup"] {
  border-inline-start: 4px solid var(--gk2-mint);
  padding-inline-start: 12px;
}

.price-table__amount {
  font-family: var(--atelier-serif);
  font-size: 1.25rem;
  line-height: 1.1;
  color: var(--gk2-ink);
  white-space: nowrap;
}

body.locale-fa .price-table__amount {
  font-family: var(--atelier-persian);
  font-weight: 700;
}

.price-table__none {
  font-size: 0.88rem;
  color: var(--gk2-ink-soft);
}

.price-table__plus {
  font-weight: 600;
}

.price-table__note {
  margin: clamp(14px, 2vw, 20px) 0 0;
  max-width: 68ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

/* What each package buys — a FEATURE COMPARISON, packages as columns and
   features as rows. The home page still carries the three cards; here a parent
   is comparing across a row, which is what a table is for, and the level tones
   wash the package headers the same way they wash those cards. */
.price-compare__title {
  margin: clamp(28px, 4vw, 44px) 0 0;
  font-size: 1.4rem;
}

.price-compare__lead {
  margin: 8px 0 0;
  max-width: 68ch;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

.price-compare__scroll {
  margin-block-start: 18px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: 18px;
  border: 1px solid var(--gk2-line);
  background: var(--gk2-white);
  box-shadow: 0 10px 28px rgb(var(--gk2-ink-rgb) / 0.06);
}

.price-compare {
  width: 100%;
  min-width: 420px;
  border-collapse: collapse;
}

.price-compare th,
.price-compare td {
  padding: 16px 18px;
  text-align: center;
  vertical-align: middle;
  border-block-end: 1px solid var(--gk2-line);
}

.price-compare tbody tr:last-child th,
.price-compare tbody tr:last-child td {
  border-block-end: 0;
}

.price-compare__feature-head,
.price-compare tbody th {
  text-align: start;
  font-weight: 600;
}

.price-compare tbody th {
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--gk2-ink);
  background: color-mix(in srgb, var(--gk2-paper) 70%, var(--gk2-white));
}

.price-compare__feature-head {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gk2-ink-soft);
  background: var(--gk2-paper-2);
}

.price-compare__pkg {
  --level-tone: var(--gk2-line);
  position: relative;
  min-width: 9.5rem;
  background: color-mix(in srgb, var(--level-tone) 16%, var(--gk2-white));
  border-block-end: 3px solid var(--level-tone);
}

.price-compare thead th.price-compare__pkg:nth-child(2) { --level-tone: var(--gk2-level-1); }
.price-compare thead th.price-compare__pkg:nth-child(3) { --level-tone: var(--gk2-level-2); }
.price-compare thead th.price-compare__pkg:nth-child(4) { --level-tone: var(--gk2-level-3); }

.price-compare__pkg-name {
  display: block;
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--gk2-ink);
}

.price-compare__pkg-desc {
  display: block;
  margin-block-start: 6px;
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--gk2-ink-soft);
}

.price-compare__cell--yes {
  background: color-mix(in srgb, var(--gk2-leaf) 10%, var(--gk2-white));
}

.price-compare__cell--no {
  color: var(--gk2-ink-soft);
}

/* Drawn tick, same physical borders as `.alive-level__tick`: a logical pair
   would flip under RTL and read as a reflected wedge on the Persian shop. */
.price-compare__yes {
  display: inline-block;
  inline-size: 14px;
  block-size: 8px;
  border-left: 2.5px solid var(--gk2-leaf);
  border-bottom: 2.5px solid var(--gk2-leaf);
  transform: rotate(-45deg);
  vertical-align: middle;
}

.price-compare__no {
  font-size: 0.95rem;
  font-weight: 500;
  opacity: 0.55;
}

.price-compare__note {
  margin: 14px 0 0;
  max-width: 68ch;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--gk2-ink-soft);
}

@media (max-width: 640px) {
  .price-table th,
  .price-table td {
    padding: 12px;
  }
}

/* --- the two plain pages: About and Contact ------------------------------
 *
 * Both are one column of prose and a grid of short blocks, so they share one
 * set of rules rather than each carrying its own. They reuse `alive-catalog`
 * for the page frame and `alive-catalog__head` for the heading, which is what
 * gives them the catalogue's own measure and rhythm; only the blocks below
 * the heading are new.
 */

.page-lede .alive-catalog__head p {
  max-width: 68ch;
}

.page-grid,
.contact-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: clamp(24px, 4vw, 40px) 0 0;
  padding: 0;
  list-style: none;
}

/* The contact page is plain contact information rather than four promo cards:
   one method per line, icon first, then the one thing a visitor is here to
   copy or tap. */
.contact-list {
  justify-content: start;
}

.page-grid__item {
  padding: 22px;
  border-radius: 16px;
  background: var(--gk2-white);
  border: 1px solid var(--gk2-line);
}

.page-grid__item h2 {
  margin: 0 0 8px;
  font-family: var(--atelier-serif);
  font-size: 1.1rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--gk2-ink);
}

.page-grid__item p {
  margin: 8px 0 0;
  color: var(--gk2-ink-soft);
  font-size: 0.95rem;
}

.contact-inline-links {
  margin: clamp(12px, 3vw, 20px) 0 0;
  padding: 0;
  list-style: none;
}

.contact-inline-links__item {
  display: flex;
  align-items: center;
  gap: 12px;
}

.contact-inline-links__item + .contact-inline-links__item {
  margin-top: 12px;
}

.contact-inline-links__icon {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 12px;
  background: var(--gk2-paper-2);
  color: var(--gk2-ink);
}

.contact-inline-links__icon svg {
  display: block;
  width: 22px;
  height: 22px;
}

.contact-inline-links__icon--email {
  background: color-mix(in srgb, var(--gk2-sun) 18%, var(--gk2-white));
  color: color-mix(in srgb, var(--gk2-sun-deep) 72%, var(--gk2-ink));
}

.contact-inline-links__icon--phone {
  background: color-mix(in srgb, #8ec8ff 24%, var(--gk2-white));
  color: color-mix(in srgb, #4d7ec9 72%, var(--gk2-ink));
}

.contact-inline-links__icon--bale {
  background: color-mix(in srgb, #82ead0 26%, var(--gk2-white));
  color: color-mix(in srgb, #1e7d69 76%, var(--gk2-ink));
}

.contact-inline-links__icon--instagram {
  background: color-mix(in srgb, #f2a2c9 24%, var(--gk2-white));
  color: color-mix(in srgb, #9a3f72 74%, var(--gk2-ink));
}

/* The value itself is the destination. `dir="ltr"` is in the markup for the
   number and handles, because a bidi run can reorder them into a different
   sequence on a right-to-left page. */
.contact-inline-links__value,
.contact-inline-links .footer-email-link {
  display: inline-block;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  cursor: pointer;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--gk2-ink);
  text-decoration: underline;
  text-decoration-color: var(--gk2-sun-deep);
  text-underline-offset: 3px;
  word-break: break-word;
}

.contact-inline-links__value:hover,
.contact-inline-links__value:focus-visible,
.contact-inline-links .footer-email-link:hover,
.contact-inline-links .footer-email-link:focus-visible {
  color: var(--gk2-ink);
}

.contact-inline-links--footer {
  margin-top: 0;
}

.contact-inline-links--footer .contact-inline-links__item + .contact-inline-links__item {
  margin-top: 10px;
}

.page-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-block-start: clamp(24px, 4vw, 36px);
}

/* --- the masthead's two dropdowns ---------------------------------------
 *
 * <details>/<summary>, not a :hover panel. On a touch screen the first tap IS
 * the hover, so a hover panel opens and then follows the link underneath it;
 * and a panel that needs JavaScript is a menu that is simply missing when a
 * script fails. This opens on click, on Enter and on Space for free, announces
 * its own state to a screen reader, and main.js only adds the two conveniences
 * a native <details> has no opinion about: closing the OTHER one when this one
 * opens, and closing on an outside click or Escape.
 */

.nav-drop {
  position: relative;
}

.nav-drop__toggle {
  cursor: pointer;
  list-style: none;
  gap: 6px;
}

/* Safari draws its own triangle through ::-webkit-details-marker and ignores
   `list-style: none`, so the row comes out with two arrows in it. */
.nav-drop__toggle::-webkit-details-marker {
  display: none;
}

/* A real element, not `.nav-drop__toggle::after`. That pseudo is ALREADY this
   masthead's hover underline (gooki-redesign.css: absolute, inset-inline 0,
   bottom -7px, scaleX(0)), and a second rule for it at the same specificity
   only overrides the properties it names — so the chevron inherited the
   underline's position and printed as a mark centred UNDER the word. */
.nav-drop__arrow {
  width: 7px;
  height: 7px;
  /* PHYSICAL borders, and the one place in this sheet that is right. A chevron
     pointing DOWN is the same shape in both directions, so the logical pair
     mirrors it into a chevron pointing left on the Persian shop — which reads
     as "back", not as "there is more under here". */
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 160ms var(--gk2-ease);
}

.nav-drop[open] > .nav-drop__toggle .nav-drop__arrow {
  transform: translateY(1px) rotate(-135deg);
}

.nav-drop__menu {
  position: absolute;
  inset-block-start: calc(100% + 8px);
  /* Logical, so the panel hangs from the same edge of its own summary in both
     directions — a physical `left` puts the Persian panel off the wrong end. */
  inset-inline-start: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: max(220px, 100%);
  padding: 8px;
  border: 1px solid var(--gk2-line);
  border-radius: 16px;
  background: var(--gk2-white);
  box-shadow: var(--gk2-float);
}

.nav-drop__menu a {
  padding: 9px 12px;
  border-radius: 10px;
  color: var(--gk2-ink);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.nav-drop__menu a:hover,
.nav-drop__menu a:focus-visible {
  background: var(--gk2-paper-2);
}

/* In the collapsed masthead the bar is already a vertical panel, so a second
   floating one on top of it would cover the items under it. It becomes an
   accordion instead: the submenu pushes the rest of the list down, indented
   with a logical margin so it reads as belonging to the row above it. */
body.nav-compact .nav-drop__menu {
  position: static;
  min-width: 0;
  margin-block-start: 2px;
  margin-inline-start: 12px;
  padding: 2px 0;
  border: 0;
  border-inline-start: 2px solid var(--gk2-line);
  border-radius: 0;
  background: none;
  box-shadow: none;
}

body.nav-compact .nav-drop__menu a {
  white-space: normal;
}
