@charset "UTF-8";
/* Rank V = "voiced, devoicing does not happen". Renamed from E. */
/* Rank X = "exception: rule and real-life production disagree".
   Deliberately purple-violet rather than another red/orange/blue, so it
   reads as a distinct category (an override) rather than another point on
   the A-D / V scale. Renamed from F. */
* {
  box-sizing: border-box;
}

html, body {
  height: 100%;
  margin: 0;
}

/* Smooth-scroll programmatic scroll_into_view() calls (e.g. clicking an
   example far down the page jumps to the input at the top). */
html {
  scroll-behavior: smooth;
}

body {
  background: #fbfaf6;
  color: #111827;
  font-family: "Noto Sans JP", "Hiragino Sans", "Yu Gothic", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

main {
  max-width: 880px;
  margin: 0 auto;
  padding: 2.5rem 1.25rem 4rem;
  display: grid;
  gap: 1.5rem;
}

header {
  text-align: left;
  border-bottom: 1px solid #e5e7eb;
  padding-bottom: 1rem;
}
header h1 {
  margin: 0 0 0.4rem;
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  letter-spacing: 0.02em;
}
header .subtitle {
  margin: 0;
  color: #374151;
  font-size: 0.95rem;
}
header .subtitle .ranks-inline b {
  font-weight: 700;
}

.input-section {
  display: grid;
}
.input-section .kana-input {
  width: 100%;
  padding: 0.9rem 1rem;
  font: inherit;
  font-size: 1.6rem;
  color: #111827;
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  outline: none;
  transition: border-color 120ms, box-shadow 120ms;
}
.input-section .kana-input:focus {
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.18);
}
.input-section .kana-input::placeholder {
  color: #9ca3af;
}

.result-section {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 1.25rem 1.25rem 1rem;
  min-height: 5.5rem;
}
.result-section .hint {
  color: #6b7280;
  margin: 0;
  font-style: italic;
}
.result-section .nhk-resolved {
  margin: 0 0 0.85rem;
  padding: 0.55rem 0.75rem;
  background: #fff7e6;
  border: 1px solid #fcd34d;
  border-radius: 8px;
  color: #111827;
  font-size: 1.1rem;
  line-height: 1.5;
}
.result-section .nhk-resolved b {
  color: #111827;
  font-weight: 700;
}
.result-section .reading-sep {
  color: #6b7280;
  font-size: 0.85rem;
  margin: 0 0.4rem;
}
.result-section .variant-rows {
  display: grid;
  /* Has to clear the .nhk-mark badge that protrudes ~0.5rem above each
     pill — anything tighter and the row-2 badge clips into row-1. */
  gap: 1rem;
}

/* Inline kana-with-marks primitives. Used in both the result-section's
   "X reads Y" line and the header subtitle's legend snippet, so they live
   at top-level rather than nested under .result-section. */
.inline-reading {
  /* Keep one variant unbroken; line wraps go between variants instead. */
  white-space: nowrap;
}

.inline-mora {
  display: inline-block;
  position: relative;
}

.inline-mora.silenced {
  /* Stacking context so the absolute ring sits below the glyph but above
     the .nhk-resolved cream background. */
  z-index: 0;
  /* A touch of horizontal margin so the ring has visual breathing room
     without crowding neighbouring moras. */
  margin: 0 0.18em;
}
.inline-mora.silenced .inline-glyph {
  position: relative;
  display: inline-block;
  /* Tight box around the kana so the ring centres on the glyph itself,
     not on the slack of the surrounding 1.5 line-height. */
  line-height: 1;
  z-index: 1;
}
.inline-mora.silenced .silence-ring {
  /* Square overlay centered on the glyph. The SVG keeps the default
     `xMidYMid meet`, so the ellipse is rendered as a perfect circle
     inscribed in this square; no stretching, no clumped dots.
     Explicit dimensions (rather than `width/height: auto` + `inset`)
     dodge the iOS Safari bug where the SVG falls back to its 300×150
     intrinsic size and drifts to the upper-left corner. */
  top: 50%;
  left: 50%;
  width: 1.45em;
  height: 1.45em;
  transform: translate(-50%, -50%);
}

.inline-pitch-drop {
  font-weight: 700;
  color: #111827;
  margin: 0 0.05em;
}

/* AP boundary in the cream "X reads Y" box. NHK's notation uses a central
   dot ・ between accent phrases (一致団結 = いっち・だんけつ). */
.inline-ap-boundary {
  color: #111827;
  margin: 0 0.05em;
}

/* Custom tooltip. The native `title` attribute never surfaces on touch,
   so this opens on :hover for PC and on click (toggled via the .active
   class) on phones. The host span carries whatever class the caller
   passed in (e.g. .mora, .pitch-drop) so the tooltip doesn't introduce
   an extra wrapping layer.

   Behavioural details:
   - `:hover` is scoped to `(hover: hover)` so iOS Safari's "first tap
     simulates hover" doesn't conflict with the .active toggle.
   - Window-level click-away dismissal lives in the Tooltip component, so
     opening one auto-closes the other and tapping anywhere outside
     closes the active one.
   - On phones the pop is repositioned as a fixed bottom toast so it
     never clips against viewport edges and is unambiguously the single
     visible tooltip. */
.tooltip-host {
  position: relative;
  cursor: help;
}

.tooltip-pop {
  display: none;
  position: absolute;
  bottom: calc(100% + 0.35rem);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(17, 24, 39, 0.94);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 400;
  line-height: 1.35;
  padding: 0.4rem 0.55rem;
  border-radius: 6px;
  /* Auto-size to content so a short tooltip ("pitch fall after this
     mora") doesn't get the same 16rem slab as a long one. `max-content`
     gives the natural unwrapped width; `max-width` caps it and also
     clamps to the viewport so it never overflows horizontally even when
     the host pill is near a screen edge. */
  width: max-content;
  max-width: min(16rem, 100vw - 1.5rem);
  text-align: left;
  user-select: none;
  z-index: 100;
}
.tooltip-pop::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -4px;
  border: 4px solid transparent;
  border-top-color: rgba(17, 24, 39, 0.94);
}

@media (hover: hover) {
  .tooltip-host:hover > .tooltip-pop {
    display: block;
  }
}
.tooltip-host.active > .tooltip-pop {
  display: block;
}

/* Touch devices: anchor the pop to the bottom edge of the viewport as a
   toast. Long text gets a margin on each side instead of clipping, and a
   fresh tooltip lands in the same toast slot the previous one occupied.
   Detected via `(hover: none)` — viewport-width heuristics break on
   tablets / fold devices, but hover capability cleanly separates
   pointer-driven from finger-driven inputs. */
@media (hover: none) {
  .tooltip-pop {
    position: fixed;
    bottom: 1rem;
    left: 0.75rem;
    right: 0.75rem;
    top: auto;
    transform: none;
    width: auto;
    max-width: none;
    text-align: center;
    font-size: 0.9rem;
    padding: 0.6rem 0.8rem;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  }
  .tooltip-pop::after {
    display: none;
  }
}
/* Inline-flow version of the absolutely-positioned .nhk-mark badge — same
   amber colour family so the legend snippet in the subtitle reads as the
   same UI element the user sees floating above a mora pill. */
.nhk-tag {
  display: inline-block;
  background: #b45309;
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  vertical-align: 0.05em;
}

.variant-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.variant-row .moras {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.45rem;
  align-items: flex-start;
  flex: 1;
}

.variant-label {
  flex-shrink: 0;
  width: 1.4rem;
  color: #6b7280;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: right;
  user-select: none;
}

.pitch-drop {
  /* Align with the kana row — top of pill — not the rank-badge row, so the
     fall mark flows with the moras rather than floating between rows.
     Stays selectable: ＼ is part of the transcription users copy out. */
  align-self: flex-start;
  padding-top: 0.55rem;
  font-size: 1.6rem;
  line-height: 1;
  font-weight: 700;
  color: #111827;
  margin: 0 -0.15rem;
}

/* Inline ＼ used in the header help text. */
.pitch-drop-inline {
  font-weight: 700;
  color: #111827;
}

/* AP boundary in the pill row. Matches .pitch-drop's vertical alignment so
   the ・ sits with the kana, not the rank badges. Stays selectable for the
   same reason — copy-pastable transcription. */
.ap-boundary {
  align-self: flex-start;
  padding-top: 0.55rem;
  font-size: 1.6rem;
  line-height: 1;
  color: #111827;
  margin: 0 -0.05rem;
}

.mora {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  padding: 0.55rem 0.55rem 0.4rem;
  min-width: 2.6rem;
  background: #ffffff;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  border-bottom-width: 4px;
  transition: transform 120ms;
  /* Hover lift only on devices that actually hover. On touch, iOS Safari
     would simulate :hover on first tap and apply the transform, which
     promotes .mora to a containing block for any `position: fixed`
     descendant — the tooltip would then resolve inside the ~50px pill
     instead of the viewport, breaking the mobile bottom-toast layout. */
  /* NHK-marked silenced mora in the variant rows: orange-bordered pill with
     a tinted background and a small "NHK" corner badge. The dotted-circle
     treatment is reserved for the inline reading in .nhk-resolved. */
}
@media (hover: hover) {
  .mora:hover {
    transform: translateY(-1px);
  }
}
.mora .mora-text {
  font-size: 1.6rem;
  line-height: 1;
  color: #111827;
}
.mora .mora-badge {
  margin-top: 0.35rem;
  font-size: 0.72rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #6b7280;
  /* Reserve a fixed line so non-candidate moras (empty badge) keep the
     same pill height as ranked ones. */
  height: 0.72rem;
  /* Rank letter is meta annotation, not part of the transcription —
     keep it out of text selections so copying picks up the kana only. */
  user-select: none;
}
.mora.rank-A {
  border-bottom-color: #dc2626;
  background: rgba(220, 38, 38, 0.06);
}
.mora.rank-A .mora-badge {
  color: #dc2626;
}
.mora.rank-B {
  border-bottom-color: #ea580c;
  background: rgba(234, 88, 12, 0.06);
}
.mora.rank-B .mora-badge {
  color: #ea580c;
}
.mora.rank-C {
  border-bottom-color: #ca8a04;
  background: rgba(202, 138, 4, 0.06);
}
.mora.rank-C .mora-badge {
  color: #ca8a04;
}
.mora.rank-D {
  border-bottom-color: #16a34a;
  background: rgba(22, 163, 74, 0.06);
}
.mora.rank-D .mora-badge {
  color: #16a34a;
}
.mora.rank-V {
  border-bottom-color: #2563eb;
  background: rgba(37, 99, 235, 0.06);
}
.mora.rank-V .mora-badge {
  color: #2563eb;
}
.mora.rank-X {
  border-bottom-color: #9333ea;
  background: rgba(147, 51, 234, 0.06);
}
.mora.rank-X .mora-badge {
  color: #9333ea;
}
.mora.rank-none-candidate {
  border-bottom-style: dashed;
  border-bottom-color: #6b7280;
}
.mora.rank-none-candidate .mora-badge {
  color: #6b7280;
}
.mora.rank-none {
  border-bottom-color: #e5e7eb;
}
.mora.nhk-silenced {
  box-shadow: 0 0 0 2px #b45309;
  background: #fff7e6;
}
.mora.nhk-silenced .mora-text {
  color: #78350f;
}
.mora .nhk-mark {
  position: absolute;
  top: -0.5rem;
  right: -0.4rem;
  background: #b45309;
  color: #fff;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.05rem 0.32rem;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  pointer-events: none;
  /* "pick" is a UI annotation, never part of the copied transcription. */
  user-select: none;
}

/* Used inline (in .nhk-resolved). Absolute-positioned so it doesn't push the
   glyph; the parent .inline-glyph carries the line-height: 1 that makes the
   ring centre on the kana itself. Per-context blocks set explicit
   top/left/width/height so iOS Safari doesn't fall back to the SVG's
   intrinsic 300×150 default size. */
.silence-ring {
  position: absolute;
  z-index: -1;
  pointer-events: none;
}

/* Standalone version of the same SVG, sized in-line with text rather than
   absolute-overlaid on a kana. Used in the subtitle's legend snippet to
   show what a dotted-circle marker looks like. */
.ring-glyph {
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  vertical-align: -0.2em;
}

.legend {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 1rem 1.25rem 1.1rem;
}
.legend h2 {
  margin: 0 0 0.6rem;
  font-size: 1rem;
  color: #374151;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.legend ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}
.legend li {
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: 0.75rem;
  align-items: start;
}
.legend li .badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 6px;
  font-weight: 700;
  color: #ffffff;
}
.legend li.rank-A .badge {
  background: #dc2626;
}
.legend li.rank-B .badge {
  background: #ea580c;
}
.legend li.rank-C .badge {
  background: #ca8a04;
}
.legend li.rank-D .badge {
  background: #16a34a;
}
.legend li.rank-V .badge {
  background: #2563eb;
}
.legend li.rank-X .badge {
  background: #9333ea;
}
.legend li .meaning {
  display: grid;
  gap: 0.1rem;
}
.legend li .meaning .ja {
  font-size: 0.95rem;
  color: #111827;
}
.legend li .meaning .en {
  font-size: 0.85rem;
  color: #374151;
}
.legend li .meaning .rule {
  font-size: 0.78rem;
  color: #6b7280;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

.examples {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 1rem 1.25rem 1.1rem;
}
.examples h2 {
  margin: 0 0 0.4rem;
  font-size: 1rem;
  color: #374151;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.examples .hint {
  margin: 0 0 0.8rem;
  color: #6b7280;
  font-size: 0.85rem;
}
.examples details {
  border-top: 1px solid #e5e7eb;
  padding: 0.6rem 0 0.4rem;
}
.examples details:first-of-type {
  border-top: none;
  padding-top: 0;
}
.examples details summary {
  cursor: pointer;
  font-weight: 600;
  color: #374151;
  padding: 0.25rem 0;
  list-style: none;
}
.examples details summary::-webkit-details-marker {
  display: none;
}
.examples details summary::before {
  content: "▸";
  display: inline-block;
  width: 1.1rem;
  color: #6b7280;
  transition: transform 120ms;
}
.examples details[open] > summary::before {
  transform: rotate(90deg);
}
.examples details ul {
  list-style: none;
  padding: 0.4rem 0 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.examples .example-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  background: #fbfaf6;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 0.45rem 0.7rem;
  font: inherit;
  color: #111827;
  cursor: pointer;
  transition: background 120ms, border-color 120ms, transform 120ms;
}
.examples .example-btn:hover {
  background: #ffffff;
  border-color: #c7c2b6;
  transform: translateY(-1px);
}
.examples .example-btn .ex-kana {
  font-size: 1.05rem;
  letter-spacing: 0.02em;
}
.examples .example-btn .ex-gloss {
  font-size: 0.78rem;
  color: #6b7280;
  margin-top: 0.05rem;
}

footer {
  color: #6b7280;
  font-size: 0.8rem;
  text-align: center;
  padding-top: 0.5rem;
}
footer p {
  margin: 0;
}

/* "Back to examples" floating action button. Appears after the user
   clicks an example (which scrolls the input into view from far down the
   page) so they can return to where they were without manual scrolling.
   Self-dismisses when the user is most of the way back. */
.back-to-examples-fab {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 50;
  background: rgba(17, 24, 39, 0.94);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 0.6rem 1rem;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
  transition: background 120ms, transform 120ms;
  animation: fab-fade-in 0.18s ease-out;
}
.back-to-examples-fab:hover {
  background: rgb(0, 0, 0);
  transform: translateY(-1px);
}

@keyframes fab-fade-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
