/* Word Detail Styles */

.word-detail-card {
    border-radius: 0.75rem;
    box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
    border: none;
    padding: 2rem;
}

.word-main h1 {
    font-size: 3.5rem;
    /* Large Thai Text */
    line-height: 1.2;
    margin-bottom: 0.5rem;
    color: var(--ink);
}

@media (max-width: 768px){
    .word-main h1 {
        font-size: 2.5rem;
    }
}

.word-romanization .romanization {
    color: var(--color-primary);
    font-weight: 600;
    font-size: 1.25rem;
    font-family: var(--font-family-romanization);
}

.word-romanization .ipa {
    color: var(--ink-faint);
    margin-left: 0.5rem;
    cursor: help;
}

.tone-info {
    font-family: monospace;
    color: var(--ink-muted);
}

/* Audio Speed Buttons.
   The circle itself is the shared `.action-circle` control (assets/css/tailwind/
   input.css): white with a slate border and glyph, a slate wash on hover, and
   emerald + a pulsing ring while playing. Only the JS-driven states and the
   "½" label live here — the gold hover that used to override the circle is
   gone, so the button reads like every other control on the page. */
.audio-speed-btn {
    position: relative;
    transition: all 0.2s;
}

.audio-speed-btn .slow-label {
    font-size: 0.6rem;
    font-weight: 700;
    position: absolute;
    bottom: 4px;
    right: 6px;
    line-height: 1;
    color: var(--ink-faint);
}

.audio-speed-btn .bi-play-fill {
    font-size: 1.1rem;
}

.audio-speed-btn:hover .slow-label {
    color: var(--ink-label);
}

.audio-speed-btn.playing .slow-label {
    color: var(--color-primary);
}

.audio-speed-btn.loading {
    opacity: 0.6;
    pointer-events: none;
}

.audio-speed-btn.disabled {
    opacity: 0.35;
    cursor: not-allowed;
    pointer-events: none;
}

.audio-speed-btn.no-audio {
    animation: shake 0.3s ease;
}

@keyframes shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-3px); }
    75% { transform: translateX(3px); }
}

/* Action Buttons */
.ui-btn-icon {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    background: var(--surface-hover);
    border: none;
    border-radius: 0.5rem;
    transition: background 0.2s;
    color: var(--ink-label);
    text-decoration: none;
}

.ui-btn-icon:hover {
    background: var(--surface-active);
    color: var(--ink);
}

/* Sections */
.definition-main {
    font-size: 1.25rem;
    color: var(--ink);
}

.definition-extended,
.word-usage p,
.word-cultural p {
    color: var(--ink-muted);
    line-height: 1.7;
}

.word-usage,
.word-cultural {
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--border);
}

h3 {
    font-size: 0.875rem;
    color: var(--ink-faint);
    text-transform: uppercase;
    font-weight: 600;
    margin-bottom: 0.5rem;
}

/* Examples */


.example-card .thai-text {
    font-size: 1.25rem;
    margin-bottom: 0.5rem;
    display: block;
}

.example-card .romanization {
    color: var(--ink-faint);
    font-size: 0.875rem;
    margin-bottom: 0.25rem;
    display: block;
}







/* Word Meta Badge Alignment */
.word-meta .ui-badge {
    display: inline-flex;
    align-items: center;
    height: 28px;
    line-height: 1;
}

/* Tag Link Hover Effects */
.tag-link .ui-badge {
    transition: all 0.2s ease;
    transform: translateY(0);
}

.tag-link:hover .ui-badge {
    transform: translateY(-2px);
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
    filter: brightness(1.1);
}

/* Lesson Card Hover Effects */
.lesson-card {
    transition: all 0.2s ease;
    display: block;
}

.lesson-card .ui-card {
    transition: all 0.2s ease;
}

.lesson-card:hover .ui-card {
    transform: translateY(-4px);
    box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}

.lesson-card:hover {
    text-decoration: none;
}

/* Letter inspection ------------------------------------------------------- */

/* Each character of the headword is its own span so it can carry a hover
   highlight; the highlight is scoped by .letter-inspection-on, so the heading
   renders as plain text until the reader turns the toggle on. Both kinds of
   target paint through an absolutely positioned ::after — never padding, never a
   transform, either of which would reflow the word and move the letter out from
   under the cursor. */
.letter-inspection-on .word-letter[data-letter] {
    position: relative;
    cursor: pointer;
    /* Only the painted box is a target. An inline span's own box is the full
       line height at its x position, so leaving it hit-testable meant a mark
       swallowed clicks anywhere in that column — above the tone mark, next to
       the consonant, even over a neighbour. */
    pointer-events: none;
}

.letter-inspection-on .word-letter[data-letter]::after {
    content: "";
    position: absolute;
    border-radius: 0.25rem;
    pointer-events: auto;
    cursor: pointer;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
}

/* Every band is measured at runtime by letter-inspection.js: the script
   rasterizes the word's shaped prefixes (the same HarfBuzz shaping the DOM run
   uses) and pixel-diffs consecutive prefixes, so each span's band lands exactly
   on the pixels ITS character paints — however the font positions that ink
   (stacked ั+้, a tone lowered after ื or ึ, ็ riding high, ำ gluing into the
   previous base). Fixed per-class zones cannot do that: a tone paints at a
   different height over every base, so any static zone either floats above the
   ink or swallows a neighbour. The four custom properties are em units
   relative to the span box: --li-bx/--li-bw horizontal from the span origin
   (a mark's ink sits LEFT of its own origin, because under letter-spacing the
   mark span starts one spacing step after the base's advance ends),
   --li-by/--li-bh vertical from the span box top. Defaults keep an unpainted
   but clickable fallback should the measurer fail (e.g. canvas blocked). */
.letter-inspection-on .word-letter[data-letter]::after {
    left: var(--li-bx, -0.05em);
    width: var(--li-bw, 1.05em);
    top: var(--li-by, 0em);
    height: var(--li-bh, 1.2em);
}

/* On a wrapped headword a mark band (tone/vowel) hangs ABOVE its own line box
   — into the line above — and later spans paint over earlier ones, so the last
   line's bands would steal hover AND clicks from the previous line's ink
   (proven at 390 on 712/945: tapping line-1 า opened the line-2 อื dialog).
   While the mode is on, JS tags each span with the index of the rendered line
   (data-li-line); the band z-index descends per line, so at any contested
   point the EARLIER line wins and a band never leaves its own line's
   jurisdiction. Bands keep their measured ink offsets (clamping tops would
   collapse a wrapped stacked pair ั+้ into one zone and break ั). Within one
   line all bands share a z-index, so the DOM-order resolution that split
   stacked pairs into vertical zones is unchanged. Single-line words get line 0
   everywhere — no behavioural difference. */
.letter-inspection-on .word-letter[data-li-line="0"]::after { z-index: 40; }
.letter-inspection-on .word-letter[data-li-line="1"]::after { z-index: 30; }
.letter-inspection-on .word-letter[data-li-line="2"]::after { z-index: 20; }
.letter-inspection-on .word-letter[data-li-line="3"]::after { z-index: 10; }

.letter-inspection-on .word-letter[data-letter]:hover::after,
.letter-inspection-on .word-letter[data-letter]:focus-visible::after {
    background-color: rgb(33 150 243 / 0.16);
    box-shadow: 0 0 0 2px rgb(33 150 243 / 0.55);
}

/* Only the ::after paints, never the span's own box. */
.letter-inspection-on .word-letter[data-letter]:hover,
.letter-inspection-on .word-letter[data-letter]:focus-visible {
    background-color: transparent;
    box-shadow: none;
    outline: none;
}

/* One block per letter is pre-rendered inside #letterModal; the script reveals
   the clicked one, so the combining-mark carrier stays server-side. */
.letter-peek__head {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1rem;
}

.letter-peek__glyph {
    font-size: 3rem;
    line-height: 1.2;
    min-width: 4rem;
    text-align: center;
}

.letter-peek__name {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--ink);
}

.letter-peek__thai-name {
    color: var(--ink-muted);
}

.letter-peek__facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.25rem 1rem;
    margin: 0;
}

.letter-peek__facts dt {
    color: var(--ink-muted);
    font-weight: 600;
}

.letter-peek__facts dd {
    margin: 0;
    color: var(--ink);
}

/* Letter inspection — the "on" treatment.
   A dashed frame names the mode so a reader never has to infer it from the
   pressed toggle alone. The frame's padding and border are reserved in both
   states (a transparent border still occupies its 1.5px), so switching the
   mode paints the border instead of moving the word under the cursor. */
.word-thai-frame {
    --word-frame-gutter: 18px;
    --word-frame-line: 1.5px;
    /* What the frame actually adds to the left of the glyphs: the gutter plus
       the border, which is laid out in whole pixels — the 1.5px above occupies
       1px. Cancelling exactly this much lands the first glyph on the card's text
       column, and keeps the headword on the same pixel grid as the rows below. */
    --word-frame-inset: calc(var(--word-frame-gutter) + 1px);
    position: relative;
    display: inline-block;
    max-width: 100%;
    /* Bottom padding clears a ุ ู band, which reaches below the line box. */
    padding: 16px var(--word-frame-gutter) 12px;
    border: var(--word-frame-line) dashed transparent;
    border-radius: 14px;
    /* The gutter is decoration around the word, not indentation. Shift the
       painted box left by the inset, so the headword starts on the column the
       romanization, badges and definition below share — without changing the
       box's width (a negative margin would shrink the shrink-to-fit frame and
       wrap a headword that fits on one line today) and without reflowing
       anything when the mode is toggled. */
    left: calc(-1 * var(--word-frame-inset));
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.letter-inspection-on .word-thai-frame,
.word-thai-frame.letter-inspection-on {
    border-color: rgba(16, 185, 129, 0.5);
    background: rgba(16, 185, 129, 0.05);
}

.word-thai-badge {
    position: absolute;
    top: -9px;
    left: 14px;
    display: none;
    padding: 1px 8px;
    border-radius: 999px;
    background: #059669;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.word-thai-frame.letter-inspection-on .word-thai-badge {
    display: inline-block;
}

/* The mode is still in development, so its button carries a small slate chip.
   It is a label, not a second control: no hover/press state of its own. The ink
   stays grey so it reads as a footnote to the label, not a warning. On the
   pressed (emerald) pill it stays solid white with the same slate ink, because
   tinted ink on emerald cannot spare the contrast at this size. */
.letter-inspection-toggle {
    /* Turning the mode on widens the headword and squeezes this row; without
       nowrap the label drops "Beta" onto a second line and the button jumps
       from 38px to 58px tall. */
    white-space: nowrap;
}

.letter-inspection-beta {
    display: inline-flex;
    flex: none;
    align-items: center;
    padding: 1px 0.4rem;
    border: 1px solid #cbd5e1;
    border-radius: 999px;
    background: #f8fafc;
    color: #475569;
    font-size: 0.625rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.action-quiet[aria-pressed="true"] .letter-inspection-beta {
    border-color: #fff;
    background: #fff;
    color: #475569;
}

/* Opening the word up while the mode is on is the point of the mode: adjacent
   bases stop touching, so the pointer lands on the character the reader means.

   CRITICAL: the gap MUST be letter-spacing, never margin/padding and never
   display:inline-block. The spans stay plain inline so the whole headword keeps
   shaping as ONE run — that is what makes ำ (U+0E33, decomposed as ํ + า)
   render its nikhahit once instead of twice, and lets the font position a
   stacked pair like ั + ้ with its mark-to-mark rules instead of colliding at
   solo height. Measured on this stack (4x DPI, Sarabun 700): with
   margin/padding/inline-block separation the ำ circle duplicates and ั้
   collapses; with letter-spacing the ink is pixel-identical to the off state.
   letter-spacing is distributed by the shaper inside the run, so it only
   widens the boxes — painted glyph positions stay untouched.

   The extra box width lands AFTER each character, so a mark's span (its
   advance is 0) starts one spacing step late, right of the column it paints
   over; the band offsets below compensate for that shift. */
.letter-inspection-on .word-letter {
    letter-spacing: 0.14em;
}

.letter-inspection-on .word-letter:first-child {
    /* no leading gap */
}

/* The dialog explains the letter, not just names it: a silence marker that
   shows only a dash and "Special Character" tells a learner nothing. */
.letter-peek__description {
    margin: 0 0 0.75rem;
    color: var(--ink);
}

.letter-peek__guide {
    margin: 0.75rem 0 0;
    color: var(--ink-muted);
    font-size: 0.875rem;
}

.letter-peek__audio {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    margin-top: 0.35rem;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.letter-peek__audio:hover,
.letter-peek__audio:focus-visible {
    border-color: var(--ink-muted);
    background: rgb(148 163 184 / 0.12);
}
