/* In-place fade for the JS-driven language swap (lang-switch.js): it
   toggles this class, waits for the fade-out, swaps text, then removes
   it. */
[data-i18n] {
  transition: opacity 150ms ease;
}

@media (prefers-reduced-motion: no-preference) {
  .i18n-fade-out {
    opacity: 0;
  }
}

:root {
  --page-blue: #f3f7fc;
  --soft-blue: #c9e7fa;
  --tab-blue: #bfdff6;
  --active-yellow: #f8e6a6;
  --active-yellow-border: #e7bf63;
  --gold-flourish: #dfae58;

  --panel-white: #fffdf8;
  --panel-cream: #fff8ec;
  --warm-beige: #e8d1af;

  --soft-pink: #f4b2c1;
  --light-pink: #fad7df;

  --text-brown: #3d281f;
  --muted-brown: #71594c;

  --blue-heart: #91c7ee;
  --pink-heart: #f3a6b7;

  /* Native pixel dimensions of the source PNGs — verified in an
     isolated /frame-test harness before integration. Used at native
     scale so the trim/dash detail isn't blurred or squashed. */
  --frame-corner-width: 138px;
  --frame-corner-height: 139px;
  --frame-horizontal-thickness: 139px;
  --frame-vertical-thickness: 138px;

  /* Measured directly from the (already-transparent) edge PNGs: max
     alpha-channel extent of visible trim pixels is x:103–134 on
     frame-edge-h.png (vertical borders, 138px wide) and y:3–34 on
     frame-edge-v.png (horizontal borders, 139px tall) — a ~34px trim
     depth on every side. 36px clears that with a small margin, so the
     fill never shows through the trim's own transparent gaps/dashes. */
  --frame-fill-left: 36px;
  --frame-fill-right: 36px;
  --frame-fill-top: 36px;
  --frame-fill-bottom: 36px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family:
    ui-rounded,
    "Arial Rounded MT Bold",
    "Trebuchet MS",
    "Hiragino Maru Gothic ProN",
    system-ui,
    sans-serif;
  color: var(--text-brown);
  background-color: var(--page-blue);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.36) 0,
    rgba(255, 255, 255, 0.36) 50%,
    rgba(205, 231, 248, 0.2) 50%,
    rgba(205, 231, 248, 0.2) 100%
  );
  background-size: 72px 72px;
}

/* Bow/heart ornaments: each color variant is a standalone SVG file
   (static/images/home/{bow,heart}-{blue,pink,white}.svg) loaded via
   <img>, so color comes from the file, not from CSS. */
.ornament {
  display: block;
  height: auto;
}

.lace-top {
  display: block;
  position: relative;
  z-index: 2;
  width: 100%;
  height: 85px;
  flex: 0 0 auto;
  background-image: url("/static/images/home/lace-top.svg");
  background-repeat: repeat-x;
  background-position: bottom left;
  background-size: 86px 85px;
  filter: drop-shadow(0 8px 10px rgba(28, 54, 92, 0.3));
}

/* Bead strings: static, hang from the lace band, one ornament attached
   flush to the last bead. No animation. */
.bead-string {
  position: absolute;
  top: -14px;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}

.bead-string__beads {
  display: block;
  width: 22px;
  background-image: url("/static/images/home/beads.svg");
  background-repeat: repeat-y;
  background-position: top center;
  background-size: 22px 143px;
}

.bead-string__ornament {
  /* pull up into the last bead so there's no visible gap */
  margin-top: -12px;
}

.bead-string__ornament.ornament--heart {
  width: 30px;
}

.bead-string__ornament.ornament--bow {
  width: 44px;
}

/* Scattered lower decoration: static, irregular, independent of the
   bead strings. Purely a background pattern. */
/* Individual .scatter-ornament children are hand-placed with inline
   left/top percentages, several of which are intentionally just past
   0%/100% (e.g. -1.4%, 101.4%) for a scattered bleed effect at the
   panel's edge. .landing (this element's positioning ancestor) is the
   full-width row, not the narrower panel, so an unclipped ornament at
   those offsets sticks out past the actual page edge and forces
   horizontal scroll. Clipped here, at the decorative layer itself —
   not with a page-wide overflow-x rule — so the bleed effect is
   contained without touching real, non-decorative overflow causes. */
.scatter-ornaments {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.scatter-ornament {
  position: absolute;
  height: auto;
}

.landing {
  position: relative;
  z-index: 1;
  width: 100%;
  flex: 1;
  display: flex;
  justify-content: center;
  padding: 24px 16px 40px;
}

.landing__panel {
  position: relative;
  width: min(1400px, calc(100% - 48px));
  margin-inline: auto;
  min-height: 860px;
  box-sizing: border-box;
  /* No fill here — .landing__panel is only a positioning root now. The
     fill lives on .frame-fill, inset to the frame's inner boundary, so
     it never extends under the decorative corner/edge artwork. */
  background: transparent;
  border-radius: 36px;
}

/* Inner fill: clipped to the frame's visible inner contour (see the
   --frame-fill-* measurements above), so it stops exactly where the
   border trim's own opaque pixels are — not underneath the trim's
   transparent gaps, which would let it peek out past the visible line.
   .frame-interior-clip does the clipping (overflow:hidden); .frame-fill
   just fills that clipped box. Sits below the frame (z-index 0 < 1) and
   below the content (0 < 2). */
.frame-interior-clip {
  position: absolute;
  top: var(--frame-fill-top);
  right: var(--frame-fill-right);
  bottom: var(--frame-fill-bottom);
  left: var(--frame-fill-left);
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: 22px;
}

.frame-fill {
  position: absolute;
  inset: 0;
  background: #f3f7fc;
}

/* Outer page frame: one absolute overlay inside the page wrapper
   (.landing__panel), applied once, ported unchanged from the verified
   /frame-test harness (see report for the full validation).

   Two things confirmed only by inspecting the source PNGs' actual
   pixels (not assumption):

   1. The supplied edge PNGs are mislabeled relative to their content:
      "frame-edge-horizontal.png" (frame-edge-h.png) contains a
      VERTICAL accent bar + vertical dashes (repeats DOWN a side edge);
      "frame-edge-vertical.png" (frame-edge-v.png) contains a
      HORIZONTAL accent bar + horizontal dashes (repeats ACROSS a
      top/bottom edge). Mapped below by actual content, not filename.

   2. frame-corner.png is natively a TOP-RIGHT corner (its horizontal
      connector runs from the curl toward the left, its vertical
      connector runs from the curl toward the bottom) — not top-left.
      --tr gets no transform; the other three are mirrored from that. */
.decorative-frame {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: visible;
  background-color: transparent;
}

.frame-corner {
  position: absolute;
  width: var(--frame-corner-width);
  height: var(--frame-corner-height);
  object-fit: contain;
  object-position: center;
  transform-origin: center;
  background-color: transparent;
}

.frame-corner--tr {
  top: 0;
  right: 0;
  transform: none;
}

.frame-corner--tl {
  top: 0;
  left: 0;
  transform: scaleX(-1);
}

.frame-corner--br {
  right: 0;
  bottom: 0;
  transform: scaleY(-1);
}

.frame-corner--bl {
  left: 0;
  bottom: 0;
  transform: scale(-1, -1);
}

.frame-edge--top,
.frame-edge--bottom {
  position: absolute;
  left: var(--frame-corner-width);
  right: var(--frame-corner-width);
  height: var(--frame-horizontal-thickness);
  background-image: url("/static/images/home/frame-edge-v.png");
  background-repeat: repeat-x;
  background-position: center;
  background-size: auto 100%;
  background-color: transparent;
}

.frame-edge--top {
  top: 0;
}

.frame-edge--bottom {
  bottom: 0;
  transform: rotate(180deg);
}

.frame-edge--left,
.frame-edge--right {
  position: absolute;
  top: var(--frame-corner-height);
  bottom: var(--frame-corner-height);
  width: var(--frame-vertical-thickness);
  background-image: url("/static/images/home/frame-edge-h.png");
  background-repeat: repeat-y;
  background-position: center;
  background-size: 100% auto;
  background-color: transparent;
}

.frame-edge--left {
  left: 0;
  transform: scaleX(-1);
}

.frame-edge--right {
  right: 0;
}

.landing__inner {
  /* Just clears the frame's footprint so content doesn't sit under the
     artwork — the fill itself comes from .frame-fill, a separate inset
     layer, so this doesn't need its own background/margin. */
  position: relative;
  z-index: 2;
  padding-inline: calc(var(--frame-corner-width) + 18px);
  padding-top: calc(var(--frame-corner-height) + 18px);
  padding-bottom: calc(var(--frame-corner-height) + 18px);
}

/* Language-selection controls + greeting mascot: side-by-side on desktop,
   stacked on narrower viewports (see the shared breakpoint below). Both
   children use flex: 1 1 min(...) so they wrap onto their own line
   instead of shrinking below a usable width. */
.intro {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 28px;
  margin: 0 0 40px;
}

.lang-select {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  flex: 1 1 320px;
  max-width: 380px;
  min-width: 0;
}

.lang-select__label {
  min-width: 0;
  font-weight: 700;
  font-size: 20px;
  text-align: center;
}

.lang-select__group {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}

.lang-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 184px;
  height: 64px;
  padding: 0 14px;
  border-radius: 20px;
  min-width: 0;
  border: 2px dashed var(--blue-heart);
  background: var(--panel-white);
  color: var(--text-brown);
  font-family: inherit;
  font-weight: 700;
  font-size: 19px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(28, 54, 92, 0.08);
  transition:
    background 160ms ease,
    box-shadow 160ms ease,
    border-color 160ms ease,
    color 160ms ease,
    transform 160ms ease;
}

/* Same soft-bloom hover glow as .card, in this button's own blue accent. */
.lang-btn:hover {
  background: var(--tab-blue);
  border-color: var(--blue-heart);
  box-shadow:
    0 0 2px rgba(145, 199, 238, 0.55),
    0 0 6px rgba(145, 199, 238, 0.35),
    0 0 14px rgba(145, 199, 238, 0.22),
    0 4px 10px rgba(28, 54, 92, 0.08);
}

.lang-btn:focus-visible {
  outline: 3px solid rgba(95, 153, 198, 0.55);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  .lang-btn:hover {
    transform: translateY(-3px) scale(1.015);
  }

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

.lang-btn__flag {
  width: 30px;
  height: 26px;
  border-radius: 5px;
  flex-shrink: 0;
}

.lang-btn span {
  min-width: 0;
  white-space: nowrap;
}

.hero {
  position: relative;
  text-align: center;
  margin: 0 0 20px;
}

.current-lang {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 0 8px;
}

.current-lang__icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.current-lang__label {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--muted-brown);
}

.current-lang__links {
  display: flex;
  gap: 4px;
}

.current-lang__link {
  appearance: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text-brown);
  text-decoration: none;
  background: var(--panel-white);
  border: 1.5px solid rgba(191, 223, 246, 0.8);
  border-radius: 8px;
  padding: 3px 8px;
  transition:
    background 160ms ease,
    border-color 160ms ease;
}

.current-lang__link:hover {
  border-color: var(--blue-heart);
}

.current-lang__link:focus-visible {
  outline: 3px solid rgba(95, 153, 198, 0.55);
  outline-offset: 2px;
}

.current-lang__link--active {
  background: var(--blue-heart);
  border-color: var(--blue-heart);
}

.hero__bow-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 4px;
}

.hero__bow {
  width: 60px;
  height: auto;
}

.hero__gold-flourish {
  width: 360px;
  max-width: 28vw;
  height: auto;
  opacity: 0.5;
  flex-shrink: 1;
  min-width: 0;
}

.hero__gold-flourish--reverse {
  transform: scaleX(-1);
}

.hero__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  row-gap: 8px;
  gap: 20px;
}

.hero__title {
  margin: 0;
  min-width: 0;
  font-size: clamp(34px, 3.5vw, 45px);
  font-weight: 800;
  color: var(--text-brown);
}

.hero__flourish {
  width: 70px;
  height: auto;
  opacity: 0.9;
}

.greeting {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Matched to roughly the .lang-select block's own height (label +
     gap + button) so the paired block reads as one balanced unit
     instead of a tall card next to a short one. */
  height: 160px;
  flex: 1 1 380px;
  max-width: 460px;
  min-width: 0;
  background-image: url("/static/images/home/greeting-form.svg");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  /* Left padding reserves the mascot's own footprint (left offset +
     width, see .greeting__mascot below) so the centered label's content
     box starts clear of her — sized this way instead of relying on the
     box being "wide enough", which broke once .intro made this box
     share width with the language selector instead of spanning the
     full section. */
  padding: 0 24px 0 136px;
  margin: 0;
}

.greeting__mascot {
  position: absolute;
  left: 14px;
  /* greeting-form.svg's drawn bubble only fills the middle ~55% of its
     own viewBox height (its top/bottom margins are transparent), so
     bottom:0 would let her feet hang below the visible bubble instead
     of standing on it. ~33px lines her feet up with the bubble's own
     drawn bottom edge at this box height. */
  bottom: 33px;
  width: 110px;
  height: auto;
  filter: drop-shadow(0 6px 10px rgba(28, 54, 92, 0.18));
}

.greeting__label {
  min-width: 0;
  font-weight: 700;
  font-size: 32px;
  letter-spacing: 0.02em;
  /* .greeting's padding is asymmetric (136px left vs 24px right) to clear
     the mascot, which pulls flex's centering off the box's true midpoint
     by half that difference — shift back to compensate. */
  transform: translateX(-56px);
}

.greeting::before,
.greeting::after {
  content: "\2661";
  position: absolute;
  font-size: 18px;
  opacity: 0.55;
}

.greeting::before {
  top: 16px;
  right: 24px;
  color: var(--pink-heart);
}

.greeting::after {
  bottom: 16px;
  right: 48px;
  color: var(--blue-heart);
}

.bottom-bow-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 28px 0 0;
}

.bottom-bow {
  display: block;
  width: 60px;
  height: auto;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.card {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr);
  align-items: center;
  column-gap: 24px;
  height: 210px;
  min-width: 0;
  background-image: url("/static/images/home/types-form.svg");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  /* Symmetric padding, unlike an earlier version of this rule that
     padded the bottom extra to "make room" for .card__info — that
     shifted the align-items:center icon+text block upward instead,
     since .card__info is position:absolute and never needed layout
     space reserved for it in the first place. */
  padding: 20px 28px;
  color: var(--text-brown);
  transition: transform 160ms ease;
}

/* Silhouette-hugging hover glow: a duplicate of the card artwork, sized
   and positioned identically to the real background so its own pixels
   are invisible, with a drop-shadow filter — unlike box-shadow,
   drop-shadow follows the image's actual alpha shape, so the glow
   traces the SVG's curved and decorative outer edge instead of the
   element's rectangular box. Kept at z-index: 0, strictly behind
   .card__icon / .card__text (z-index: 2), because an absolutely
   positioned layer paints above static in-flow content by default —
   without the explicit z-index split, the glow covered the icon and
   label instead of sitting behind them.

   Layered with blur (not a hard-edged offset) so it reads as a soft
   bloom (bright core + wider, softer falloff) rather than a thin flat
   line — a hard-edged 1px/2px shadow has much less visual presence
   against the page's pale #f3f7fc background. Regular blue (--tab-blue,
   #bfdff6) instead of white per request. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: url("/static/images/home/types-form.svg");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  filter:
    drop-shadow(0 0 2px rgba(191, 223, 246, 0.45))
    drop-shadow(0 0 6px rgba(191, 223, 246, 0.3))
    drop-shadow(0 0 14px rgba(191, 223, 246, 0.18));
  opacity: 0;
  transition: opacity 220ms ease;
  pointer-events: none;
}

.card:hover::before {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .card:hover {
    transform: translateY(-3px) scale(1.015);
  }
}

.card__icon {
  position: relative;
  z-index: 2;
  opacity: 1;
  visibility: visible;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 144px;
  height: 144px;
  justify-self: center;
}

.card__icon img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Kanji and Dictionary artwork reads slightly larger than Listening/Games
   at the same 144px box, so trim them down a touch to match. */
.card:nth-child(1) .card__icon img,
.card:nth-child(2) .card__icon img {
  width: 85%;
  height: 85%;
}

.card__text {
  position: relative;
  z-index: 2;
  opacity: 1;
  visibility: visible;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.card__label {
  font-weight: 700;
  font-size: 34px;
}

.card__accent {
  font-size: 1rem;
  color: var(--pink-heart);
  opacity: 0.65;
  letter-spacing: 0.05em;
}

/* Reusable info-icon + tooltip: same two classes (.card__info,
   .tooltip) on every card, differing only by the id each tooltip is
   described-by. Pure CSS hover/focus reveal — the button is natively
   focusable and :focus-visible covers keyboard use, so no JS is
   needed to open/close it. */
.card__info {
  position: absolute;
  right: 24px;
  bottom: 20px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid #edc472;
  background: rgba(255, 253, 248, 0.9);
  cursor: help;
  transition:
    background 160ms ease,
    border-color 160ms ease;
}

.card__info:hover,
.card__info:focus-visible {
  background: #614031;
  border-color: #614031;
}

.card__info:focus-visible {
  outline: 3px solid rgba(95, 153, 198, 0.55);
  outline-offset: 2px;
}

.card__info-icon {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  transition: opacity 160ms ease;
}

.card__info-icon--hover {
  opacity: 0;
}

.card__info:hover .card__info-icon--default,
.card__info:focus-visible .card__info-icon--default {
  opacity: 0;
}

.card__info:hover .card__info-icon--hover,
.card__info:focus-visible .card__info-icon--hover {
  opacity: 1;
}

.tooltip {
  position: absolute;
  right: 18px;
  bottom: 54px;
  z-index: 4;
  width: max-content;
  max-width: min(240px, calc(100vw - 32px));
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--text-brown);
  color: var(--panel-white);
  font-size: 0.82rem;
  font-weight: 400;
  line-height: 1.4;
  text-align: left;
  box-shadow: 0 8px 18px rgba(28, 54, 92, 0.25);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 160ms ease,
    visibility 160ms ease;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .tooltip {
    transform: translateY(4px);
    transition:
      opacity 180ms ease,
      transform 180ms ease,
      visibility 180ms ease;
  }
}

.card__info:hover + .tooltip,
.card__info:focus-visible + .tooltip {
  opacity: 1;
  visibility: visible;
  transform: none;
}

@media (max-width: 1100px) {
  .landing__panel {
    min-height: 0;
  }

  .intro {
    flex-direction: column;
    gap: 20px;
  }

  .lang-select,
  .greeting {
    flex: 1 1 auto;
    width: 100%;
    max-width: 420px;
  }

  .lang-btn {
    width: 100%;
    max-width: 200px;
    height: 56px;
    font-size: 17px;
  }

  .hero__title {
    font-size: clamp(20px, 4.7vw, 31px);
  }

  .hero__flourish {
    width: 44px;
  }

  .hero__gold-flourish {
    width: 224px;
    max-width: 26vw;
  }

  .greeting {
    height: auto;
    min-height: 150px;
    flex-direction: column;
    text-align: center;
    padding: 24px 20px 20px;
  }

  .greeting__mascot {
    position: static;
    width: 130px;
    margin-bottom: 8px;
  }

  .greeting__label {
    font-size: 30px;
    transform: none;
  }

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

  .card {
    grid-template-columns: 130px minmax(0, 1fr);
    height: auto;
    padding: 16px 20px;
  }

  .card__icon {
    width: 120px;
    height: 120px;
  }

  .card__label {
    font-size: 26px;
  }

  .bead-string,
  .scatter-ornaments {
    display: none;
  }

  :root {
    --frame-corner-width: 40px;
    --frame-corner-height: 40px;
    --frame-horizontal-thickness: 40px;
    --frame-vertical-thickness: 40px;
    --frame-fill-left: 10px;
    --frame-fill-right: 10px;
    --frame-fill-top: 10px;
    --frame-fill-bottom: 10px;
  }
}

/* Narrow phones: the 130px fixed icon column has no room left once the
   frame padding is subtracted from a ~320–375px viewport, so cards drop
   to a single stacked column (icon above text) instead of shrinking the
   icon column below a usable size. */
@media (max-width: 480px) {
  :root {
    --frame-corner-width: 18px;
    --frame-corner-height: 18px;
    --frame-horizontal-thickness: 18px;
    --frame-vertical-thickness: 18px;
    --frame-fill-left: 6px;
    --frame-fill-right: 6px;
    --frame-fill-top: 6px;
    --frame-fill-bottom: 6px;
  }

  .landing__inner {
    padding-inline: calc(var(--frame-corner-width) + 10px);
  }

  .card {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
    row-gap: 8px;
    padding: 18px 16px 40px;
  }

  .card__icon {
    width: 96px;
    height: 96px;
  }

  .card__text {
    align-items: center;
  }

  .lang-btn {
    width: auto;
    min-width: 140px;
    max-width: 100%;
    flex: 0 1 auto;
    padding: 0 12px;
    font-size: 15px;
  }

  .lang-btn__flag {
    width: 22px;
    height: 19px;
  }
}
