/* =============================================================================
   nikō  ·  suapagina.pages.dev/niko/

   Every colour below was sampled out of the client's own menu PDFs, not chosen.
   club: violet #5D48F6 + chartreuse #D2D752 on cream #F8F6EE
   bā:   green #4F6E5E + ink #312340 on cream #F7F7E8
   ============================================================================= */

:root {
  --violet:    #5D48F6;
  --violet-dk: #4534D4;
  --lime:      #D2D752;
  --lime-dk:   #A8AD31;
  --green:     #4F6E5E;
  --green-dk:  #3E5A4B;
  --ink:       #312340;
  --pink:      #DE5093;

  --paper:     #F8F6EE;
  --paper-2:   #EFEBDD;
  --text:      #241A31;
  --text-2:    #5A5064;
  --rule:      rgba(36, 26, 49, .14);

  --wrap: 1180px;
  --gut: 24px;
  --r: 18px;            /* one radius scale: 18px surfaces, 999px interactive */
  --bar-h: 64px;
  --sec: clamp(46px, 6vw, 84px);   /* one vertical rhythm for every section */

  /* Single locked theme. This identity is a two-colour print system: cream ground,
     violet and chartreuse for the club, green and ink for the bā. A dark variant
     inverted the ground the marks were designed to sit on and flattened the ink
     block against the page, so the page ships in the brand's own palette only. */
  color-scheme: only light;
}

/* ---------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font: 400 clamp(16px, 1.05vw, 17.5px)/1.65 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
h1, h2, h3 { margin: 0; line-height: 1.06; letter-spacing: -.022em; font-weight: 800; }
p { margin: 0; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--violet); color: #fff; padding: 12px 18px; border-radius: 0 0 var(--r) 0;
}
.skip:focus { left: 0; }

:focus-visible { outline: 3px solid var(--pink); outline-offset: 3px; border-radius: 4px; }

/* the wordmark: their name, set tight, with the macron they actually use */
.wordmark { font-weight: 800; letter-spacing: -.045em; font-size: 1.5rem; }
.wordmark--lg { font-size: 2.6rem; display: block; margin-bottom: .5rem; }

/* ---------------------------------------------------------------- header */
.bar {
  position: sticky; top: 0; z-index: 40;
  height: var(--bar-h);
  display: flex; align-items: center; gap: 18px;
  padding-inline: var(--gut);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.bar__mark { text-decoration: none; margin-right: auto; }
.bar__nav { display: none; gap: 26px; }
.bar__nav a {
  text-decoration: none; font-weight: 500; font-size: .95rem;
  color: var(--text-2); padding: 6px 0;
  border-bottom: 2px solid transparent;
  transition: color .18s, border-color .18s;
}
.bar__nav a:hover { color: var(--text); border-bottom-color: var(--lime-dk); }
@media (min-width: 780px) { .bar__nav { display: flex; } }

/* Anchors clear the sticky bar. */
section[id] { scroll-margin-top: calc(var(--bar-h) + 12px); }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 24px; border-radius: 999px;
  font-weight: 700; font-size: 1rem; text-decoration: none; white-space: nowrap;
  transition: transform .16s, background-color .18s, color .18s, box-shadow .18s;
}
.btn:active { transform: translateY(1px) scale(.985); }

.btn--solid  { background: var(--lime);   color: #2E3208; }
.btn--solid:hover  { background: #E1E66A; }
/* Chartreuse on violet is only 3.65:1, so button labels use the pale tint of the same
   hue that already appears in their menu artwork. */
.btn--ghost  { background: transparent; color: #EFF1C6; box-shadow: inset 0 0 0 2px rgba(239,241,198,.55); }
.btn--ghost:hover  { background: rgba(239,241,198,.16); }

.btn--onviolet { background: var(--lime); color: #2E3208; }
.btn--onviolet:hover { background: #E1E66A; }
.btn--ongreen  { background: #F7F7E8; color: var(--green-dk); }
.btn--ongreen:hover  { background: #fff; }
/* The deep magenta is the one their own poster artwork uses; the lighter pink cannot
   carry white text at AA. */
.btn--ondark   { background: #AC2366; color: #fff; }
.btn--ondark:hover   { background: #C42E76; }

.lnk {
  font-weight: 600; font-size: .95rem;
  text-decoration: none; border-bottom: 1.5px solid currentColor;
  padding-bottom: 1px; opacity: .92;
  transition: opacity .16s;
}
.lnk:hover { opacity: 1; }

/* ---------------------------------------------------------------- hero */
/* Built like their own menu cover: a flat violet field, the character large and standing
   on the bottom edge rather than floating in the middle of it, and 寿司クラブ set big
   beside him. --hero-pb is shared so the mark can bleed exactly to the section edge. */
.hero {
  --hero-pb: clamp(0px, 3vw, 40px);
  position: relative;
  background: var(--violet);
  color: var(--lime);
  padding: clamp(36px, 5vw, 60px) 0 var(--hero-pb);
  overflow: clip;             /* structural, never overflow-x on body */
}
/* The club room is a wall of LED lightboxes. A dot field at this strength reads as the
   field having a texture rather than as a pattern, and never competes with the type. */
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(rgba(247, 249, 218, .13) 1px, transparent 1.4px);
  background-size: 20px 20px;
}
.hero__inner {
  position: relative;
  width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut);
  display: grid; gap: clamp(24px, 3vw, 40px);
  align-items: end;
}
/* The line break is set by hand in the markup, so balancing would fight it. The cap is
   the largest size at which "from the retro future" still holds one line inside the type
   column at every width; the invariant script fails the build if that stops being true. */
.hero__type h1 {
  font-size: clamp(2rem, 4.9vw, 3.75rem);
  letter-spacing: -.035em;
}
.hero__sub {
  margin-top: 1.05rem; max-width: 40ch;
  font-size: clamp(1.05rem, 1.5vw, 1.22rem);
  color: #EDEFC0;
}
.hero__cta { margin-top: 1.8rem; display: flex; flex-wrap: wrap; gap: 12px; }

.hero__mark {
  justify-self: center; align-self: end;
  display: flex; align-items: flex-end; gap: clamp(12px, 1.8vw, 24px);
}
/* Only the illustration bleeds. Cropping a drawing well into the torso reads as a crop;
   grazing it exactly at the artwork's open line-ends read as a clipping bug. The
   katakana never bleeds, because a word sliced through a glyph just looks broken. */
.hero__mark .face {
  margin-bottom: calc((var(--hero-pb) + clamp(26px, 4.5vw, 76px)) * -1);
}
.kata { margin-bottom: clamp(8px, 1.6vw, 22px); }
/* 寿司クラブ, set vertically, straight off their own menu cover */
.kata {
  display: none;
  width: clamp(24px, 3vw, 42px); height: clamp(180px, 26vw, 330px);
  background-color: rgba(210, 215, 82, .8);
  -webkit-mask: url(marks/club-kata.png) bottom center / contain no-repeat;
          mask: url(marks/club-kata.png) bottom center / contain no-repeat;
}
@media (min-width: 880px) {
  /* The mark stands on the bottom edge; the type is optically centred against it
     rather than sharing that baseline, which left the left column bottom-heavy. */
  .hero__inner { grid-template-columns: minmax(0, 1fr) auto; }
  .hero__type { align-self: center; padding-bottom: clamp(8px, 1.6vw, 22px); }
  .hero__mark { justify-self: end; }
  .kata { display: block; }
}

/* The client's real artwork, lifted from their menu PDF and used as an alpha mask so
   it takes its colour from the block it sits in. Every path in that artwork is a fill,
   not a stroke, so a draw-on is impossible; a solid mark gets a travelling sheen
   instead, like light crossing a lit sign. Background only paints where masking is
   supported, so an unsupported browser gets nothing rather than a lime rectangle. */
.face, .cat, .house__art { background: none; }
@supports ((-webkit-mask-image: url(#m)) or (mask-image: url(#m))) {
  .face { background: var(--lime); }
  .cat, .house__art { background-color: currentColor; }
}
.face {
  position: relative; overflow: hidden;
  width: clamp(230px, 36vw, 470px);
  aspect-ratio: 1023 / 1234;
  -webkit-mask: url(marks/club-face.png) center / contain no-repeat;
          mask: url(marks/club-face.png) center / contain no-repeat;
}
.face i { position: absolute; inset: -12% -45%; translate: -62% 0; }

/* ---------------------------------------------------------------- casas */
.casas { padding: var(--sec) 0; }
.h2 {
  font-size: clamp(1.9rem, 4.2vw, 3.1rem);
  letter-spacing: -.032em;
  text-wrap: balance;
}
.lede {
  margin-top: .85rem; font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  color: var(--text-2); max-width: 46ch;
}

.casas__grid {
  margin-top: clamp(32px, 4vw, 52px);
  display: grid; gap: 24px;
}
@media (min-width: 900px) {
  /* Asymmetry comes from the column widths, not a vertical offset: offsetting one
     card just produced two ragged bottoms and a hole under the shorter one. */
  .casas__grid { grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr); align-items: stretch; }
}

.casa {
  border-radius: var(--r); overflow: hidden;
  display: flex; flex-direction: column;
}
.casa__body { flex: 1; }
.casa--club { background: var(--violet); color: #EDEFC0; }
.casa--ba   { background: var(--green);  color: #EDEDDC; }
.casa__pic img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.casa--club .casa__pic img { object-position: 50% 62%; }
.casa--ba   .casa__pic img { object-position: 50% 64%; }   /* keeps the plate and the napkin in frame */
.casa__body { padding: clamp(22px, 3vw, 32px); }
.casa__body h3 { font-size: clamp(1.5rem, 2.6vw, 2rem); }
.casa--club .casa__body h3 { color: var(--lime); }
.casa--ba   .casa__body h3 { color: #F7F7E8; }
.casa__hood {
  margin-top: .3rem; font-weight: 600; font-size: .95rem;
  text-transform: lowercase; opacity: .82;
}
.casa__line { margin-top: 1rem; font-size: 1.05rem; }

.facts { margin: 1.5rem 0 0; display: grid; grid-template-columns: auto 1fr; gap: .45rem 1.1rem; }
.facts dt { font-weight: 700; font-size: .82rem; opacity: .7; padding-top: .18rem; }
.facts dd { margin: 0; font-size: .98rem; }
.facts--tight { gap: .55rem 1.2rem; }

.casa__links { margin-top: auto; padding-top: 1.7rem; display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; }
.casa__note { margin-top: 1.1rem; font-size: .88rem; opacity: .78; }

/* ---------------------------------------------------------------- pratos */
/* Sits on the same ground as .casas, so the join is one gap, not two stacked paddings. */
.pratos { padding: 0 0 var(--sec); }
.pratos__head { max-width: 44ch; }

.masonry { margin-top: clamp(30px, 4vw, 48px); columns: 1; column-gap: 20px; }
@media (min-width: 640px)  { .masonry { columns: 2; } }
@media (min-width: 1000px) { .masonry { columns: 3; } }

.dish {
  break-inside: avoid;
  margin: 0 0 20px;
  background: var(--paper-2);
  border-radius: var(--r);
  overflow: hidden;
  transition: transform .22s cubic-bezier(.16,1,.3,1), box-shadow .22s;
}
.dish:hover { transform: translateY(-3px); box-shadow: 0 14px 34px rgba(36,26,49,.14); }
.dish img { width: 100%; }
.dish figcaption { padding: 18px 20px 22px; }
.dish h3 { font-size: 1.22rem; }
.dish p { margin-top: .5rem; font-size: .93rem; color: var(--text-2); }

.veg {
  margin-top: clamp(24px, 3vw, 36px);
  padding: clamp(26px, 3.2vw, 40px);
  border-radius: var(--r);
  background: var(--lime);
  color: #2E3208;
  display: grid; gap: clamp(20px, 2.6vw, 34px);
}
@media (min-width: 860px) { .veg { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; } }
.veg h3 { font-size: clamp(1.2rem, 2.1vw, 1.65rem); max-width: 22ch; }
.veg p { margin-top: .8rem; max-width: 46ch; }
.veg__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.veg__list li {
  border: 1.5px solid rgba(46,50,8,.42); border-radius: 999px;
  padding: 5px 13px; font-size: .88rem; font-weight: 600;
}

/* ---------------------------------------------------------------- bā */
.ba {
  background: var(--green);
  color: #EDEDDC;
  padding: var(--sec) 0;
}
.ba .h2 { color: #F7F7E8; }
.ba .lede { color: #EDF0E0; }
.ba__top { display: grid; gap: clamp(28px, 4vw, 48px); align-items: center; }
@media (min-width: 900px) { .ba__top { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); } }
.ba__type > p { margin-top: 1.1rem; max-width: 54ch; }
.ba__type em { font-style: normal; font-weight: 700; color: #F7F7E8; }
.ba__type strong { color: #F7F7E8; }
.ba__drinks {
  margin-top: 1.4rem; font-weight: 600; line-height: 1.75;
  color: #F7F7E8;
}
.ba__drinks span { display: inline-block; margin-top: .4rem; font-weight: 400; color: #D8DCC4; font-size: .93rem; }
.ba__type .btn { margin-top: 1.8rem; }

.ba__art { justify-self: center; color: #EDEDDC; }
.cat {
  width: clamp(190px, 26vw, 300px); aspect-ratio: 827 / 885;
  -webkit-mask: url(marks/ba-cat.png) center / contain no-repeat;
          mask: url(marks/ba-cat.png) center / contain no-repeat;
}

.house { margin: clamp(36px, 5vw, 60px) 0 0; text-align: center; color: #DCE0CB; }
.house__art {
  width: min(100%, 640px); margin-inline: auto;
  aspect-ratio: 1380 / 1010;
  -webkit-mask: url(marks/ba-house.png) center / contain no-repeat;
          mask: url(marks/ba-house.png) center / contain no-repeat;
}
.house figcaption { margin-top: 1rem; font-size: .86rem; color: #E4E8D6; }

.ba__floor {
  margin-top: clamp(36px, 5vw, 64px);
  padding-top: clamp(28px, 3.5vw, 40px);
  border-top: 1px solid rgba(237,237,220,.28);
  max-width: 62ch;
}
.ba__floor h3 { font-size: clamp(1.2rem, 2.2vw, 1.6rem); color: #F7F7E8; }
.ba__floor p { margin-top: .7rem; }

.ba__pics { margin-top: clamp(30px, 4vw, 48px); display: grid; gap: 18px; }
@media (min-width: 640px)  { .ba__pics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .ba__pics { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.ba__pics figure { margin: 0; border-radius: var(--r); overflow: hidden; }
.ba__pics img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
/* Three items in a two-column grid: one has to span, and the one that does is chosen
   for having a master large enough to fill a full-width slot at 2x. */
@media (min-width: 640px) and (max-width: 999px) { .ba__pics figure:last-child { grid-column: span 2; } }

/* ---------------------------------------------------------------- bailinho */
.bailinho {
  background: var(--ink);
  color: #E9E4F2;
  padding: var(--sec) 0;
}
.bailinho .h2 { color: #fff; }
.bailinho .lede { color: #C4BAD4; }
.bailinho__head { max-width: 52ch; }
.bailinho__head .btn { margin-top: 1.6rem; }
.bailinho__pics { margin-top: clamp(30px, 4vw, 48px); display: grid; gap: 18px; }
@media (min-width: 640px)  { .bailinho__pics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .bailinho__pics { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.bailinho__pics figure { margin: 0; border-radius: var(--r); overflow: hidden; }
.bailinho__pics img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
@media (min-width: 640px) and (max-width: 999px) { .bailinho__pics figure:first-child { grid-column: span 2; } }
.credit { margin-top: 1.2rem; font-size: .84rem; color: #A9A0B8; }

/* ---------------------------------------------------------------- prático */
.pratico { padding: var(--sec) 0; }
.pratico__grid { margin-top: clamp(30px, 4vw, 48px); display: grid; gap: 20px; }
@media (min-width: 820px) { .pratico__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.card { padding: clamp(24px, 3vw, 34px); border-radius: var(--r); }
.card--club { background: var(--violet); color: #EDEFC0; }
.card--ba   { background: var(--green);  color: #EDEDDC; }
.card h3 { font-size: clamp(1.35rem, 2.4vw, 1.8rem); }
.card--club h3 { color: var(--lime); }
.card--ba   h3 { color: #F7F7E8; }
.card .facts { margin-top: 1.3rem; }
.card a { text-decoration: none; border-bottom: 1.5px solid currentColor; }
.pratico__note { margin-top: 1.6rem; font-size: .95rem; color: var(--text-2); max-width: 60ch; }
.pratico__note a { font-weight: 600; }

/* ---------------------------------------------------------------- footer */
.foot { background: var(--violet); color: #EDEFC0; padding: calc(var(--sec) * .85) 0; }
.foot__inner { display: grid; gap: 28px; }
@media (min-width: 760px) { .foot__inner { grid-template-columns: minmax(0, 1fr) auto; align-items: start; } }
.foot .wordmark--lg { color: var(--lime); }
.foot__brand p { color: #EAEDC8; }
.foot__links { display: flex; flex-wrap: wrap; gap: 10px 22px; }
.foot__links a { text-decoration: none; font-weight: 600; border-bottom: 1.5px solid rgba(210,215,82,.5); }
.foot__links a:hover { border-bottom-color: var(--lime); }

/* =============================================================================
   MOTION
   Reveals are scroll-driven where supported, so the work happens off the main
   thread. Start states are gated behind .js: with no JavaScript the page is
   fully visible. Nothing here is decorative -- each reveal follows reading order.
   ============================================================================= */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .js:not(.no-sdt) .reveal {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 24%;
    }
  }
  .js.no-sdt .reveal { opacity: 0; translate: 0 20px; transition: opacity .55s ease, translate .55s cubic-bezier(.16,1,.3,1); }
  .js.no-sdt .reveal.in { opacity: 1; translate: 0 0; }

  /* Light crossing the mark, the way it crosses their lit sign. */
  .face i {
    background: linear-gradient(102deg, transparent 42%, #F7F9DA 50%, transparent 58%);
    animation: sheen 8s cubic-bezier(.5,0,.5,1) infinite;
  }
  /* The cat is asleep. It breathes. */
  .cat { animation: breathe 6.5s ease-in-out infinite; }
}

@keyframes rise { from { opacity: 0; translate: 0 22px; } to { opacity: 1; translate: 0 0; } }
@keyframes sheen { 0%, 10% { translate: -62% 0; } 62%, 100% { translate: 62% 0; } }
@keyframes breathe { 0%, 100% { scale: 1; } 50% { scale: 1.022; } }

@media (prefers-reduced-motion: reduce) {
  .dish { transition: none; }
  .dish:hover { transform: none; }
}
