/* Font declarations live in fonts/typography.css, loaded alongside this file.
   Both Japanese and Latin glyphs use the same two self-hosted families. */

:root {
  --color-bg: #fbf9f5;
  --color-low: #f5f3ef;
  --color-container: #efeeea;
  --color-text: #181512;
  --color-muted: #4d4540;
  --color-accent: #506354;
  --color-pale: #d0e5d2;
  --color-outline: #cfc4bd;
  --color-white: #fff;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-20: 5rem;
  --radius-sm: 0.5rem;
  --radius-lg: 1rem;
  --content: 76rem;
  --font-body: "Zen Kaku Gothic New", "Hiragino Kaku Gothic ProN", "Yu Gothic", sans-serif;
  --font-heading: "Shippori Mincho", "Yu Mincho", "Hiragino Mincho ProN", serif;

  color-scheme: light;
  font-family: var(--font-body);
  background: var(--color-bg);
  color: var(--color-text);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-width: 320px;
  background: var(--color-bg);
  font-size: 1rem;
  line-height: 1.85;
  line-break: strict;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
}

button,
input,
select,
textarea {
  font: inherit;
}

:focus-visible {
  outline: 0.1875rem solid var(--color-accent);
  outline-offset: 0.1875rem;
}

/* Browser surfaces carry the palette: juniper-pale selection keeps the
   apothecary world in the visitor's own highlight color; the caret takes
   the action green so text entry points at the same place focus does. */
::selection {
  background: var(--color-pale);
  color: var(--color-text);
}

input,
select,
textarea {
  caret-color: var(--color-accent);
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-heading);
  font-weight: 500;
  text-wrap: balance;
  word-break: auto-phrase;
  overflow-wrap: anywhere;
}

/* Japanese-first hierarchy: generous leading keeps multiline Mincho legible. */
h1 {
  font-size: clamp(2rem, 1.65rem + 1vw, 2.5rem);
  line-height: 1.5;
}

h2 {
  font-size: 1.75rem;
  line-height: 1.55;
}

h3 {
  font-size: 1.375rem;
  line-height: 1.6;
}

h4 {
  font-size: 1.125rem;
  line-height: 1.6;
}

.hero__content h1 {
  max-inline-size: 18ic;
  margin: 0 auto var(--space-6);
  font-size: clamp(2.25rem, 1.5rem + 2.75vw, 4rem);
  line-height: 1.55;
  letter-spacing: 0.02em;

  /* ジュネヴァ must never split mid-word: keep-all is the fallback that
     auto-phrase degrades to in browsers without phrase support.
     overflow-wrap: anywhere on the shared heading rule stays the
     emergency valve. */
  word-break: keep-all;
  word-break: auto-phrase;
}

p {
  text-wrap: pretty;
}

.education-section p,
.serving-section p,
.content-page p,
.product-description p {
  max-inline-size: 68ch;
  max-inline-size: 38ic;
}

/* Description paragraph spacing lives here — not with the product component
   rules below — so specificity keeps ascending toward the education lede and
   the later component rules (stylelint no-descending-specificity). */
.product-description p {
  margin-block: 0 var(--space-4);
}

/* About page, footer social links, BASE-controlled content pages, and the
   payment-logos row. These scoped element selectors (a, ul, li, button,
   select, ...) live with the base rules so their specificity stays
   non-descending against the component rules below (stylelint
   no-descending-specificity). */
.content-page {
  width: min(100% - 2rem, 48rem);
  margin-inline: auto;
  padding-block: var(--space-12);
  overflow-wrap: anywhere;
}

/* Footer social links render only inside the official BASE blocks, so they
   appear exactly when the operator configures the matching account. Text
   labels keep each link self-describing without third-party icon assets. */
.social-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.social-links a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-1) var(--space-2);
}

/* Stable state modifiers for generated media and status output: the no-image
   placeholder container and the distinct sold-out / coming-soon labels. */
.product-card__media--no-image,
.product-gallery__item--no-image {
  background: var(--color-container);
}

.product-card__state--sold-out,
.product-card__state--coming-soon {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.product-card__state--coming-soon {
  background: var(--color-pale);
  color: var(--color-text);
}

.product-summary h1 {
  margin-block: 0;
  font-size: clamp(1.75rem, 1.5rem + 1vw, 2.25rem);
  line-height: 1.45;
  overflow-wrap: anywhere;
  text-wrap: balance;
}

/* Product metadata description lists use the specification-row pattern:
   muted small-cap labels over body values on hairline rules. These element
   selectors live with the base rules so their specificity stays
   non-descending against the component rules below (stylelint
   no-descending-specificity). */
.product-metadata dl {
  display: grid;
  grid-template-columns: minmax(5rem, 9rem) minmax(0, 1fr);
  margin-block: 0;
}

.product-metadata dt,
.product-metadata dd {
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-outline);
}

/* The label's line box matches the 1rem / 1.85 value beside it, so both
   baselines share the row. */
.product-metadata dt {
  padding-right: var(--space-4);
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 700;
  line-height: calc(1.85rem / 0.875);
  letter-spacing: 0.08em;
}

.product-metadata dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* The homepage's editorial sections and the product description run their
   headings at the system's responsive display scale. These element-final
   rules live with the base element rules so specificity stays
   non-descending against the BASE-generated content rules below. */
.education-section h2,
.serving-section h2,
.values-section h2 {
  font-size: clamp(2rem, 1.65rem + 1vw, 2.5rem);
  line-height: 1.5;
}

/* Inside a product description, headings sit below the product title:
   h2 at 1.5rem, h3 and h4 at the subtitle scale. */
.product-description h2 {
  font-size: 1.5rem;
  line-height: 1.55;
}

/* BASE-controlled content ({PageContents}) rendered on Contact, Privacy,
   Law, and other BASE pages. Typography, forms, tables, links, and errors
   are styled without suppressing or altering the generated behavior. */
.base-page-contents {
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
  padding-block: var(--space-12);
  overflow-wrap: anywhere;
}

.base-page-contents:empty {
  display: none;
}

.base-page-contents a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 0.125rem;
}

.base-page-contents h1,
.base-page-contents h2,
.base-page-contents h3,
.base-page-contents h4 {
  margin-block: var(--space-6) var(--space-2);
  line-height: 1.6;
}

.base-page-contents h1:first-child,
.base-page-contents h2:first-child,
.base-page-contents h3:first-child,
.base-page-contents h4:first-child {
  margin-top: 0;
}

.base-page-contents p,
.base-page-contents li,
.base-page-contents dd,
.base-page-contents dt {
  line-height: 1.85;
}

.base-page-contents p {
  max-inline-size: 68ch;
  max-inline-size: 38ic;
}

.base-page-contents ul,
.base-page-contents ol {
  padding-left: var(--space-6);
}

/* Form controls stay at least 44px tall (2.75rem) for touch targets. */
.base-page-contents input,
.base-page-contents select,
.base-page-contents textarea {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text);
}

.base-page-contents textarea {
  min-height: 8rem;
}

.base-page-contents label {
  display: block;
  margin-block: var(--space-4) var(--space-2);
  font-weight: 700;
}

.base-page-contents button,
.base-page-contents input[type="submit"],
.base-page-contents input[type="button"] {
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-6);
  border: 0;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-white);
  font-weight: 700;
  cursor: pointer;
}

/* Tables keep their semantics; on narrow screens the table itself scrolls
   horizontally inside the content container. */
.base-page-contents table {
  display: block;
  max-width: 100%;
  margin-block: var(--space-4);
  overflow-x: auto;
  border-collapse: collapse;
}

.base-page-contents th,
.base-page-contents td {
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-outline);
  text-align: left;
}

.base-page-contents th {
  background: var(--color-low);
  font-weight: 700;
}

/* Errors are conveyed by icon and weight, never by color alone. */
.base-page-contents [class*="error"] {
  color: #b3261e;
  font-weight: 700;
}

.base-page-contents [class*="error"]::before {
  content: "!";
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  margin-right: var(--space-2);
  border-radius: 50%;
  background: #b3261e;
  color: var(--color-white);
  font-weight: 700;
  line-height: 1.25rem;
  text-align: center;
}

/* Privacy and law pages: contained cards with wrapping text and scrollable
   wide tables; long legal copy never breaks the layout. */
.base-page-contents #privacy,
.base-page-contents #law {
  max-width: 100%;
  padding: var(--space-6);
  background: var(--color-white);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg);
  text-align: left;
}

/* Contact input / confirm / complete sections generated by BASE. */
.base-page-contents .inquirySection {
  padding: var(--space-6);
  background: var(--color-white);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-lg);
}

.base-page-contents .inquirySection dl {
  margin: 0;
}

.base-page-contents .inquirySection dt {
  margin-block: var(--space-4) var(--space-2);
  font-weight: 700;
}

.base-page-contents .inquirySection dd {
  margin: 0;
}

.base-page-contents #privacy dt {
  margin-top: var(--space-4);
  font-weight: 700;
}

.base-page-contents #inquiryConfirmSection dd {
  padding-left: var(--space-6);
}

/* The completion CTA is a link; :where() keeps it at the shared link
   specificity while still scoping the button treatment to that section. */
.base-page-contents :where(#inquiryCompleteSection) a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  margin-top: var(--space-6);
  padding: var(--space-2) var(--space-6);
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-white);
  font-weight: 700;
  text-decoration: none;
}

.base-page-contents #law .law_attention {
  margin-block: var(--space-4);
  padding: var(--space-4);
  background: var(--color-low);
  border-radius: var(--radius-sm);
}

.base-page-contents #law .atobaraiTerm {
  margin-block: var(--space-6);
}

.base-page-contents #law .atobaraiTerm__body {
  padding-left: var(--space-6);
}

/* BASE payment-logos output: a wrapping subordinate row under the legal and
   contact navigation. No payment names or logos are written in source. */
.payment-methods {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-2);
  color: var(--color-muted);
  font-size: 0.875rem;
}

.payment-methods img {
  width: auto;
  height: 2rem;
}

.payment-methods ul,
.payment-methods li {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Every interactive target is at least 44px (2.75rem) tall. */
.menu-toggle,
.skip-link,
.site-logo,
.site-footer__brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
}

.skip-link {
  position: fixed;
  z-index: 1000;
  inset: 0 auto;
  transform: translateY(-120%);
  padding: var(--space-4);
  background: var(--color-white);
}

.skip-link:focus {
  transform: translateY(0);
}

.site-header {
  position: sticky;
  z-index: 100;
  top: 0;
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) auto;
  align-items: center;
  min-height: 4.5rem;

  /* The fixed #baseMenu (cart + BASE mark) overlays the top-right at every
     width, so the right band it covers is always reserved out, not just on
     desktop — otherwise the centered logo slides underneath it on mobile. */
  padding: 0 calc(var(--space-4) + 9rem) 0 var(--space-4);
  background: color-mix(in srgb, var(--color-bg) 92%, transparent);
  border-bottom: 1px solid var(--color-outline);
  backdrop-filter: blur(1rem);
}

.site-logo {
  grid-column: 2;
  justify-self: center;
  min-width: 0;
  max-width: 100%;

  /* Text-logo lockup for "NOMIKURABE Jenever". BASE renders its logo tag here;
     when it is text (local preview and the no-image fallback) it must read
     as the full brand and stay clear of the fixed #baseMenu band. The brand
     must never split mid-word, so wrapping is word-boundary-only (at the
     space): "NOMIKURABE" / "Jenever". Narrow widths get their own rules
     below so the 10-character first word fits without shrinking the type
     to illegibility. */
  font-family: var(--font-heading);
  font-size: 1.0625rem;
  letter-spacing: 0.14em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  color: var(--color-text);
  overflow-wrap: normal;
  word-break: normal;
}

.site-logo img {
  max-height: 2.5rem;
  width: auto;
  max-width: 100%;
}

.site-footer__brand {
  justify-self: center;
  min-width: 0;
  max-width: 100%;
  font-family: var(--font-heading);
  font-size: 1.125rem;
  letter-spacing: 0.14em;
  line-height: 1.3;
  text-align: center;
  overflow-wrap: normal;
  word-break: normal;
}

/* Narrow lockup behavior: the 96-121px centered column at 320-360px cannot
   hold the 154px "NOMIKURABE" word, and mid-word splits are forbidden, so
   below 24rem the logo stacks full-width below the menu row (the first row
   stays 4.5rem tall to clear the fixed #baseMenu) and keeps its 17px/0.14em
   type. From 24rem to desktop the single-row column returns with slightly
   tighter tracking so the word still fits even with a classic scrollbar. */
@media (width < 24rem) {
  .site-header {
    grid-template-columns: 3rem minmax(0, 1fr);
    grid-template-rows: 4.5rem auto;
    padding: 0 var(--space-4) var(--space-2);
  }

  .menu-toggle {
    grid-column: 1;
    grid-row: 1;
  }

  .site-logo {
    grid-column: 1 / -1;
    grid-row: 2;
  }
}

@media (24rem <= width < 48rem) {
  .site-logo {
    letter-spacing: 0.08em;
  }
}

/* Mobile menu toggle (hamburger). Explicit column placement keeps the logo
   and nav in their columns when the toggle is display:none on desktop. */
.menu-toggle {
  grid-column: 1;
  width: 2.75rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text);
  cursor: pointer;
}

.menu-toggle span[aria-hidden="true"] {
  position: relative;
  width: 1.5rem;
  height: 0.125rem;
  background: var(--color-text);
}

.menu-toggle span[aria-hidden="true"]::before,
.menu-toggle span[aria-hidden="true"]::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 0.125rem;
  background: var(--color-text);
}

.menu-toggle span[aria-hidden="true"]::before {
  top: -0.375rem;
}

.menu-toggle span[aria-hidden="true"]::after {
  top: 0.375rem;
}

.desktop-nav {
  display: none;
  grid-column: 3;
}

.mobile-nav {
  position: fixed;
  z-index: 200;
  inset: 0;
  padding: var(--space-8);
  background: var(--color-bg);
  transform: translateX(-100%);
  transition: transform 180ms cubic-bezier(0.4, 0, 1, 1), visibility 0s 180ms;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  visibility: hidden;
  pointer-events: none;
}

.mobile-nav[aria-hidden="false"] {
  transform: translateX(0);
  transition: transform 280ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s;
  visibility: visible;
  pointer-events: auto;
}

.mobile-nav[aria-hidden="true"] {
  visibility: hidden;
  pointer-events: none;
}

html.drawer-open {
  overflow: hidden;
}

.site-footer {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-12) var(--space-4);
  text-align: center;
  background: var(--color-low);
  border-top: 1px solid var(--color-outline);
}

/* A clear gap keeps the footer links from reading as one run of text. */
.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 var(--space-6);
}

/* NTA display standard: the warning is at least as large as any price on the
   page. The product page price is 1.25rem, so match BASE's 1.3125rem warning
   panel; on product pages the footer carries the second sentence alone. */
.alcohol-warning {
  font-size: 1.3125rem;
  font-weight: 700;

  /* keep-all is what auto-phrase degrades to (Firefox), and it forbids breaks
     inside unspaced Japanese, so overflow-wrap is the valve that keeps the
     statutory sentences inside a 390px screen instead of off its edge. */
  word-break: keep-all;
  word-break: auto-phrase;
  overflow-wrap: anywhere;
}

.cart {
  position: relative;
}

.cart-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.cart-qty {
  position: absolute;
  top: -0.25rem;
  right: -0.375rem;
  min-width: 1.125rem;
  height: 1.125rem;
  padding-inline: 0.25rem;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-white);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.125rem;
  text-align: center;
}

.desktop-nav a,
.mobile-nav a,
.mobile-nav button,
.site-footer a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
}

.desktop-nav a,
.mobile-nav a,
.site-footer a {
  text-decoration: none;
}

/* Mobile drawer links fill the drawer width as touch targets. */
.mobile-nav a,
.mobile-nav button {
  justify-content: flex-start;
  padding: var(--space-2);
  text-align: left;
  border: 0;
  background: none;
  color: var(--color-text);
  cursor: pointer;
  align-self: flex-start;
}

/* Age gate: the shop's front door, set as an apothecary label on paper.
   Hidden by default and revealed only by the pre-paint script in the template,
   so a visitor without JavaScript gets the shop rather than a locked door. */
.age-gate {
  display: none;
}

html.age-gate-active .age-gate {
  position: fixed;
  z-index: 300;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--space-8) var(--space-6);
  overflow-y: auto;
  background: var(--color-bg);
}

html.age-gate-active {
  overflow: hidden;
}

.age-gate__panel {
  width: min(100%, 34rem);
  text-align: center;
}

.age-gate__mark {
  margin: 0 0 var(--space-8);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--color-outline);
  font-family: var(--font-heading);
  font-size: 1.125rem;
  overflow-wrap: anywhere;
}

.age-gate__question {
  margin: 0 0 var(--space-6);
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 4.5vw, 2.25rem);
  font-weight: 500;
  line-height: 1.5;

  /* Japanese breaks between phrases, not mid-word, where the browser can. */
  word-break: auto-phrase;
}

/* The statutory sentence is set at the system's legal scale, not shrunk. */
.age-gate__statute {
  margin: 0 0 var(--space-8);
  padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--color-outline);
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1.5;
  word-break: auto-phrase;
}

.age-gate__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.age-gate__links {
  display: flex;
  justify-content: center;
  gap: var(--space-6);
  margin: var(--space-8) 0 0;
  font-size: 0.875rem;
  color: var(--color-muted);
}

.age-gate__links a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}

.age-gate__links a:where(:hover, :focus-visible) {
  color: var(--color-accent);
}

@media (width >= 40rem) {
  .age-gate__actions {
    flex-direction: row;
    justify-content: center;
  }

  .age-gate__actions .button {
    min-width: 12rem;
  }
}

/* Child-category pills on category index pages. */
.child-categories ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
  margin: 0;
  padding: 0 0 var(--space-8);
  list-style: none;
}

.child-categories a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-low);
  text-decoration: none;
}

.child-categories a:hover,
.child-categories a:focus-visible {
  color: var(--color-accent);
}

/* The serving methods use the system's signature specification-row pattern:
   one labelled fact per row, separated by hairline rules. These ul/li rules
   live before the BASE menu rules so specificity stays non-descending. */
.serving-section ul {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.serving-section li {
  padding-block: var(--space-6);
  border-top: 1px solid var(--color-outline);
}

/* Full generated BASE menu, styled as a compact header group.
   The BASE mark and cart children stay visible; nothing is hidden or moved. */
#baseMenu {
  position: fixed;
  z-index: 150;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 4.5rem;
  max-width: 40%;
  padding-right: var(--space-4);
}

#baseMenu > ul {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

#baseMenu > ul > li {
  display: inline-flex;
  align-items: center;
}

#baseMenu a,
#baseMenu button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) var(--space-4);
  color: var(--color-text);
  text-decoration: none;
  border: 0;
  background: none;
  cursor: pointer;
}

:where(#baseMenu) .cart img,
:where(#baseMenu) .base img {
  display: block;
  width: 1.875rem;
  height: 1.875rem;
  object-fit: contain;
}

#baseMenu a:hover,
#baseMenu a:focus-visible,
#baseMenu button:hover {
  color: var(--color-accent);
}

#baseMenu li.base a {
  color: var(--color-muted);
}

@media (width >= 48rem) {
  .site-header {
    padding-inline: var(--space-8);
  }

  .site-header[data-site-header] {
    padding-right: 9rem;
  }

  .menu-toggle {
    display: none;
  }

  .site-logo {
    justify-self: start;
  }

  .desktop-nav {
    display: flex;
    gap: var(--space-6);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition: none !important;
    animation: none !important;
  }
}

/* Buttons: hero CTA and load-more (44px touch targets, no animation). */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-6);
  border: 1px solid transparent;
  border-radius: 999px;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

.button--light {
  background: var(--color-white);
  color: var(--color-text);
}

.button--accent {
  background: var(--color-accent);
  color: var(--color-white);
}

.button--outline {
  border-color: var(--color-outline);
  color: var(--color-text);
}

.button--light:hover,
.button--light:focus-visible,
.button--outline:hover,
.button--outline:focus-visible {
  color: var(--color-accent);
}

/* Dark full-bleed homepage hero with an owned image or a neutral gradient. */
.hero {
  position: relative;
  display: grid;
  align-items: end;
  min-height: min(52rem, calc(100svh - 4.5rem));
  overflow: hidden;
  background: #1a1815;
  color: var(--color-white);
}

.hero__image,
.hero__fallback,
.hero__overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero__image {
  object-fit: cover;
}

/* Bring the bottle photograph into the light once. Copy and purchase paths
   stay still and visible; no script or persistent compositor layer is needed. */
@media (prefers-reduced-motion: no-preference) {
  .hero__image {
    animation: hero-light 650ms cubic-bezier(0.16, 1, 0.3, 1);
  }
}

@keyframes hero-light {
  from {
    opacity: 0.65;
  }

  to {
    opacity: 1;
  }
}

/* Scroll-cinematic depth: the photograph lingers while the copy recedes.
   Static by default; motion only where scroll timelines exist and the
   visitor keeps motion enabled. Transform and opacity only, so the hero
   stays on the compositor. The entrance above still owns opacity-from;
   the drift below owns transform only, so the two compose. The timeline
   names the root scroller explicitly: the hero's own overflow:hidden
   would otherwise make it the nearest scroll container and freeze the
   effect at progress zero. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .hero__image {
      animation: hero-light 650ms cubic-bezier(0.16, 1, 0.3, 1), hero-drift linear both;
      animation-timeline: auto, scroll(root);
      animation-range: normal normal, 0 100vh;
      will-change: transform;
    }

    .hero__content {
      animation: hero-rise linear both;
      animation-timeline: scroll(root);
      animation-range: 0 75vh;
      will-change: transform, opacity;
    }

    .hero__overlay {
      animation: hero-shade linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100vh;
    }
  }
}

@keyframes hero-drift {
  from {
    transform: translate3d(0, -2%, 0) scale(1.04);
  }

  to {
    transform: translate3d(0, 12%, 0) scale(1.12);
  }
}

@keyframes hero-rise {
  from {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }

  to {
    transform: translate3d(0, -4rem, 0);
    opacity: 0;
  }
}

@keyframes hero-shade {
  from {
    opacity: 1;
  }

  to {
    opacity: 0.65;
  }
}

.hero__fallback {
  background: linear-gradient(135deg, #312a24, #141311);
}

.hero__overlay {
  background: linear-gradient(to top, rgb(26 24 21 / 86%), rgb(26 24 21 / 38%) 58%, rgb(26 24 21 / 20%));
}

.hero__content {
  position: relative;
  z-index: 1;
  width: min(100% - 2rem, 48rem);
  margin-inline: auto;
  padding-block: var(--space-20);
  text-align: center;
}

.hero__content p {
  max-inline-size: 32ic;
  margin-inline: auto;
  line-height: 1.9;
  color: rgb(255 255 255 / 88%);
  word-break: auto-phrase;
}

/* The hero eyebrow keeps the system's label treatment, quiet against the
   display heading above it. */
.hero__eyebrow {
  margin: 0 0 var(--space-4);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: rgb(255 255 255 / 78%);
}

/* Section spacing: collection, editorial, and value sections share the
   content column with vertical rhythm. */
.collection-section,
.education-section,
.values-section,
.serving-section {
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
  padding-block: var(--space-12);
}

/* Compact category/search result header. */
.result-header {
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
  padding-block: var(--space-8);
  text-align: center;
}

/* Dynamic collection grid: 1 column, then 2 at 40rem, then 3 at 64rem. */
.product-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
}

.product-card__media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--color-container);
}

.product-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-card__state {
  position: absolute;
  inset: auto var(--space-4) var(--space-4);
  padding: var(--space-2) var(--space-4);
  background: var(--color-text);
  color: var(--color-white);
}

.product-card__link {
  display: block;
  text-decoration: none;
}

.product-card__title {
  margin-block: var(--space-4) var(--space-2);
  font-size: 1.25rem;
  line-height: 1.6;
  text-wrap: pretty;
  overflow-wrap: anywhere;
}

.product-card__price,
.product-price {
  font-variant-numeric: lining-nums tabular-nums;
}

.product-card__link:hover .product-card__title,
.product-card__link:focus-visible .product-card__title {
  color: var(--color-accent);
}

.product-card__price del {
  color: var(--color-muted);
}

.product-card__price ins {
  color: var(--color-accent);
  font-weight: 700;
  text-decoration: none;
}

/* Load-more stays a real BASE fragment link; CSS hides it when BASE reports
   a single page, and Task 9's controller sets [hidden] for deeper pages.
   Without JS the link still shows on the final page of a multi-page listing
   (e.g. next=4 max=3) because CSS cannot compare data-next-page > data-max-page;
   JS is required to hide it there. No BASE has-next-page block exists. */
.load-more {
  display: block;
  width: max-content;
  margin: var(--space-8) auto 0;
}

.load-more[data-max-page="1"],
.load-more[hidden] {
  display: none;
}

.load-more[aria-busy="true"] {
  cursor: wait;
  opacity: 0.65;
}

.load-status {
  min-height: 1.5em;
  text-align: center;
}

/* Editorial sections: square education crop, 4:3 serving crop, neutral
   gradient fallbacks when an owned image has not been uploaded yet. Their
   headings run at the system's display scale, separated from the commerce
   grid above by a hairline rule — the apothecary drawer divider. */
.education-section {
  display: grid;
  gap: var(--space-8);
  align-items: center;
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-outline);
}

.education-section p:first-of-type {
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.6;
}

.education-section img {
  aspect-ratio: 1 / 1;
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-lg);
}

.editorial-fallback {
  background: linear-gradient(135deg, var(--color-container), var(--color-low));
  border-radius: var(--radius-lg);
}

.editorial-fallback--square {
  aspect-ratio: 1 / 1;
}

/* The values band steps one rung down the paper ramp — the tonal peak of the
   below-fold scroll — and each value reads as a labelled drawer with a
   hairline rule above it. */
.values-section {
  width: 100%;
  padding-block: var(--space-12);
  background: var(--color-low);
  border-top: 1px solid var(--color-outline);
  border-bottom: 1px solid var(--color-outline);
  text-align: center;
}

.values-section__inner {
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
}

.values-grid {
  display: grid;
  gap: var(--space-6);
}

.values-grid article {
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-outline);
}

/* Values body runs muted on the Paper Low band: headings stay ink, support
   copy steps down the hierarchy without borrowing the action green. Muted on
   Paper Low holds 8.5:1, so the tonal peak keeps AA with room to spare. */
.values-section .values-grid p {
  color: var(--color-muted);
}

.serving-section {
  display: grid;
  gap: var(--space-8);
  align-items: center;
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-outline);
}

.serving-section img {
  aspect-ratio: 4 / 3;
  width: 100%;
  object-fit: cover;
  border-radius: var(--radius-lg);
}

.editorial-fallback--landscape {
  aspect-ratio: 4 / 3;
}

.no-items {
  text-align: center;
}

.not-public {
  padding-block: var(--space-20);
  text-align: center;
}

@media (width >= 40rem) {
  .product-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (width >= 64rem) {
  .product-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (width >= 48rem) {
  .values-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .education-section {
    grid-template-columns: 1fr 1fr;
  }

  .serving-section {
    grid-template-columns: 1fr 1fr;
  }
}

/* Product detail: two-column editorial layout with the native BASE
   purchase flow. All commerce states come from BASE-generated output. */
.page--item {
  width: min(100% - 2rem, var(--content));
  margin-inline: auto;
  padding-block: var(--space-12);
}

.product-layout {
  display: grid;
  gap: var(--space-8);
  align-items: start;
}

.product-gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  align-content: start;
}

.product-gallery figure {
  margin: 0;
}

.product-gallery img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
}

.product-gallery__item--primary {
  grid-column: 1 / -1;
}

/* An unpaired trailing thumbnail would sit half-width beside empty space,
   so the orphan takes the full row instead. */
.product-gallery > :last-child:nth-child(even):not(.product-gallery__item--primary) {
  grid-column: 1 / -1;
}

.product-gallery__item--no-image {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  padding: var(--space-4);
  background: linear-gradient(135deg, var(--color-container), var(--color-low));
  border-radius: var(--radius-lg);
  color: var(--color-muted);
  font-size: 0.875rem;
}

.product-gallery__item--no-image img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
}

.product-summary {
  display: grid;
  gap: var(--space-4);
  align-content: start;
}

.product-price {
  margin-block: 0;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.5;
}

.product-price del {
  color: var(--color-muted);
}

.product-price ins {
  color: var(--color-accent);
  font-weight: 700;
  text-decoration: none;
}

/* BASE requires the warning strictly larger than the price
   (商品価格よりも大きいフォントサイズ); one pixel above the 1.25rem price
   meets that without outshouting it. Keep the two sizes in step. */
.product-summary .ageVerification,
.product-summary [class*="ageVerification"] {
  margin-block: 0;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1.3125rem;
  font-weight: 400;
  line-height: 1.6;
}

.product-summary .ageVerificationWarning {
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-low);
}

.product-summary [class*="ageVerification"] * {
  color: inherit;
}

/* BASE may wrap the warning text in its own elements and fonts; they take the
   page's body face. Icon elements are skipped so an icon-font glyph survives. */
.product-summary [class*="ageVerification"] :not(i, svg, svg *, [class*="icon"], [class*="Icon"]) {
  font-family: inherit;
  font-weight: inherit;
}

/* Original-language product name (theme.js): the Latin half of a
   「カタカナ名 / Original Name」 title, as a quiet Mincho subtitle. The key-facts
   line below stays in the body face, so the two never read as one role. */
.product-title__original {
  display: block;
  margin-top: var(--space-1);
  color: var(--color-muted);
  font-size: 1.25rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
}

.product-card__title .product-title__original {
  margin-top: 0;
  font-size: 0.9375rem;
}

/* Key facts line (theme.js): strength, volume, and origin read back from the
   specification rows, between the title and the price. */
.product-keyfacts {
  margin-block: calc(-1 * var(--space-2)) 0;
  color: var(--color-muted);
  font-size: 1rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
  font-variant-numeric: lining-nums tabular-nums;
}

/* Short introduction (theme.js): the description's opening paragraph,
   moved up under the price. */
.product-intro {
  max-inline-size: 38ic;
  margin-block: 0;
  line-height: 1.85;
  overflow-wrap: anywhere;
}

#itemAttention {
  margin-block: 0;
  color: var(--color-muted);
  font-size: 0.875rem;
  line-height: 1.5;
}

.purchaseButton {
  margin-top: 0;
}

.purchaseButton__btn {
  width: 100%;
  min-height: 3rem;
  padding: 0.75rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-white);
  cursor: pointer;
}

.purchaseButton__btn:disabled,
.purchaseButton__btn--soldOut,
.purchaseButton__btn--endOfSale,
.purchaseButton__btn--outOfStock,
.purchaseButton__btn--comingSoonStay,
.purchaseButton__btn--notApplying,
.purchaseButton__btn--disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

#purchase_form {
  display: grid;
  gap: var(--space-4);
}

.itemSelect label,
#itemSelect label {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.itemSelect select,
#itemSelect select {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text);
}

/* BASE's 商品オプション App (the required 生年月日 field) matches 数量: the
   name takes the specification-label treatment, the input is as wide and as
   tall as the select, and the guide text, counter and error stay small.
   BASE sets inline display: block on these parts, so layout stays block. */
.itemOptionElement {
  margin-bottom: var(--space-2);
}

.itemOption__name {
  margin-bottom: var(--space-2);
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.itemOption__caption {
  margin-bottom: var(--space-2);
  color: var(--color-muted);
  font-size: 0.875rem;
}

.itemOption__input {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-outline);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text);
  line-height: 1.5;
}

[data-has-error="true"] .itemOption__input {
  border-color: #b3261e;
}

.itemOption__bottomCaptionBlock {
  margin-top: var(--space-1);
  font-size: 0.875rem;
}

.itemOption__caption--error {
  color: #b3261e;
}

.itemOption__count {
  color: var(--color-muted);
  text-align: right;
}

/* The below-fold product sections open with the apothecary drawer divider —
   the same 1px Outline rule that opens the homepage's editorial sections —
   so the detail page peaks in the same scroll rhythm as the landing. */
.product-description {
  width: min(100%, 48rem);
  margin-top: 0;
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-outline);
  overflow-wrap: anywhere;
}

.product-description > :first-child {
  margin-top: 0;
}

.product-description :is(h2, h3, h4) {
  margin-block: var(--space-8) var(--space-2);
  overflow-wrap: anywhere;
  text-wrap: balance;
}

.product-description :is(h3, h4) {
  font-size: 1.125rem;
  line-height: 1.6;
}

.product-description :is(h2, h3, h4):first-child {
  margin-top: 0;
}

/* The flavor text opens with a lede at the subtitle scale, the same move as
   the homepage education section's introduction. Only a leading paragraph
   takes it; a description that opens on a heading keeps a quiet start. It
   sits last in this block so specificity keeps ascending through the
   description rules (stylelint no-descending-specificity). */
.product-description > p:first-child {
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.6;
}

.product-description p:last-child {
  margin-bottom: 0;
}

.product-metadata {
  width: min(100%, 48rem);
  margin-top: 0;
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-outline);
}

.product-metadata table {
  width: 100%;
  margin-block: 0;
  border-collapse: collapse;
  font-size: 1rem;
  line-height: 1.7;
}

.product-metadata th,
.product-metadata td {
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-outline);
  text-align: start;
  vertical-align: top;
  overflow-wrap: anywhere;
}

.product-metadata th {
  padding-right: var(--space-4);
  color: var(--color-muted);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.appsItemDetailCustom,
#appsItemDetailCustom {
  display: grid;
  gap: var(--space-6);
}

.illegal-report {
  width: min(100%, 48rem);
  margin-top: var(--space-8);
  font-size: 0.875rem;
}

@media (width >= 64rem) {
  .product-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(20rem, 0.75fr);
    gap: var(--space-8) var(--space-12);
  }

  .product-layout > * {
    grid-column: 1;
  }

  /* Sticks under the header while it fits the viewport; once taller (a long
     introduction, a short laptop screen) it pins its bottom edge instead, so
     the purchase button is always in view. theme.js supplies the height. */
  .product-layout > .product-summary {
    position: sticky;
    top: min(6rem, calc(100svh - var(--summary-height, 0px) - var(--space-6)));
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: start;
  }
}
