/*
    Visual identity is Naiova's, not this site's own.

    The tokens below are copied from the Naiova client (`client/src/style.css` and the
    PrimeVue preset in `client/src/main.ts`) so that the dictionary reads as the same
    product family. The *layout* is deliberately much plainer — Naiova is an application
    with a sidebar and a workspace; this is a reference tool that is mostly one search
    field — but the palette, type, radii, controls and focus treatment are shared.

    When Naiova's tokens change, change them here too. They are duplicated rather than
    imported on purpose: this site must not depend on the Naiova repository at build or
    run time.
*/

/*
    Two Thai letterforms, as in Naiova. Looped (มีหัว) is the traditional shape and the
    default: the loop that starts most characters is what tells several letter pairs
    apart, and a learner who lost it is reading a puzzle. Loopless is the modern
    display style, offered as a preference and never imposed.
*/
@font-face {
    font-family: "Naiova Noto Sans Thai Looped";
    src: url("/fonts/noto-sans-thai-looped-thai-400-normal.woff2") format("woff2");
    font-style: normal;
    font-weight: 400;
    font-display: swap;
}

@font-face {
    font-family: "Naiova Noto Sans Thai";
    src: url("/fonts/noto-sans-thai-thai-400-normal.woff2") format("woff2");
    font-style: normal;
    font-weight: 400;
    font-display: swap;
}

:root {
    /* --- Naiova surface palette --- */
    --naiova-bg: #f7f3ed;
    --naiova-surface: #fffdf9;
    --naiova-surface-muted: #f1ebe3;
    --naiova-text: #1e1b18;
    --naiova-text-muted: #6f675f;
    --naiova-border: #ded5cb;

    /* --- Naiova brand --- */
    --naiova-brand: #574fbd;
    --naiova-brand-strong: #40378e;
    --naiova-brand-100: #e8e4ff;
    --naiova-brand-50: #f3f1ff;
    --naiova-accent: #df5a2b;
    --naiova-accent-strong: #c8451d;

    /* --- Naiova geometry --- */
    --naiova-radius-sm: 0.4rem;
    --naiova-radius-md: 0.65rem;
    --naiova-surface-shadow: 0 0.45rem 1.4rem rgb(44 35 28 / 6%);
    --naiova-control-height: 2.65rem;

    /* Naiova's Latin stack. Not a system-ui stack: the product has a face. */
    --naiova-font: "Segoe UI", Candara, "Trebuchet MS", sans-serif;

    /* Naiova's default Thai letterform. Overridden only by an explicit preference. */
    --naiova-font-thai: "Naiova Noto Sans Thai Looped", "Leelawadee UI", Tahoma, sans-serif;

    font-family: var(--naiova-font);
    color: var(--naiova-text);
    background: var(--naiova-bg);
    font-synthesis: none;
    text-rendering: optimizeLegibility;
}

/* Set by the font preference, if the visitor has expressed one. */
:root[data-thai-font="loopless"] {
    --naiova-font-thai: "Naiova Noto Sans Thai", "Leelawadee UI", Tahoma, sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-width: 20rem;
    min-height: 100vh;
    background: var(--naiova-bg);
    font-size: 1rem;
    line-height: 1.6;
}

button,
input { font: inherit; }

a { color: var(--naiova-brand-strong); }
a:hover { color: var(--naiova-brand); }

.wrap {
    width: 100%;
    max-width: 62rem;
    margin: 0 auto;
    padding: 0 1rem;
}

/* --- accessibility ------------------------------------------------------- */

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 40;
    padding: .6rem 1rem;
    border-radius: var(--naiova-radius-sm);
    background: var(--naiova-surface);
    color: var(--naiova-text);
}

.skip-link:focus { left: .5rem; top: .5rem; }

/* Naiova's focus treatment: 2px brand outline, small offset. One rule, everywhere. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--naiova-brand);
    outline-offset: 0.2rem;
    border-radius: var(--naiova-radius-sm);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* --- chrome -------------------------------------------------------------- */

.site-header {
    border-bottom: 1px solid var(--naiova-border);
    background: color-mix(in srgb, var(--naiova-surface) 86%, var(--naiova-bg));
    padding: .8rem 0;
}

.site-header .wrap {
    display: flex;
    align-items: center;
    gap: .75rem 1rem;
    flex-wrap: wrap;
}

/* The Naiova wordmark, used as released. Nothing is redrawn or recoloured. */
.brand {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    text-decoration: none;
}

.brand img {
    display: block;
    width: 7rem;
    height: auto;
}

.brand__product {
    margin-left: .6rem;
    padding-left: .6rem;
    border-left: 1px solid var(--naiova-border);
    color: var(--naiova-text-muted);
    font-size: .95rem;
    font-weight: 650;
    white-space: nowrap;
}

.site-header form { flex: 1 1 16rem; }

main { padding: 1.75rem 0 3rem; }

.site-footer {
    border-top: 1px solid var(--naiova-border);
    color: var(--naiova-text-muted);
    font-size: .82rem;
    padding: 1.25rem 0 2rem;
}

.site-footer p { margin: .2rem 0; }

/* The language decides what the page says, so it sits above the quieter preferences. */
.language-choice {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem .6rem;
    margin: 0 0 .9rem;
}

.language-choice__label { color: var(--naiova-text-muted); }

/* On a narrow screen the four names do not fit beside the label, and the row broke after
   the third: three languages on one line and one stranded below. The label takes its own
   line instead, which keeps the four together and reads as a group. In rem, so it follows
   the reader's font size rather than only the device width. */
@media (max-width: 34rem) {
    .language-choice__label { flex: 1 0 100%; }
}

/* One shape for both, so the language being read sits in the row rather than beside it. */
.language-choice button,
.language-choice__current {
    display: inline-flex;
    align-items: center;
    height: 2.1rem;
    padding: 0 .8rem;
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-sm);
    font: inherit;
    font-weight: 650;
}

.language-choice button {
    background: var(--naiova-surface);
    color: var(--naiova-brand-strong);
    cursor: pointer;
}

.language-choice button:hover {
    border-color: color-mix(in srgb, var(--naiova-brand) 40%, var(--naiova-border));
}

/* Filled rather than outlined: the difference has to survive without colour alone being
   the signal, so it is a different background, not a different text colour. */
.language-choice__current {
    background: var(--naiova-brand-100);
    border-color: color-mix(in srgb, var(--naiova-brand) 40%, var(--naiova-border));
    color: var(--naiova-brand-strong);
}

/* A note, not an instruction: it belongs under the examples and must not compete with
   them for attention. */
.sounds-hint {
    margin: .9rem 0 0;
    color: var(--naiova-text-muted);
    font-size: .95rem;
}

/* A quiet preference, not a feature: most readers want the default and never look here. */
.font-choice {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .1rem .5rem;
    margin: 0 0 .7rem;
}

.font-choice__label { color: var(--naiova-text-muted); }

.font-choice button {
    padding: .1rem .2rem;
    border: 0;
    background: none;
    color: var(--naiova-brand-strong);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.font-choice button[aria-pressed="true"] {
    color: var(--naiova-text);
    text-decoration: none;
    font-weight: 650;
    cursor: default;
}

/*
    Each sample is pinned to the letterform it offers, not to the current one. The whole
    point of showing a character here is that the reader can see the difference: the loop
    on the traditional form against the plain stroke of the modern one.
*/
.font-choice .sample { font-size: 1.2em; }

.font-choice [data-font="looped"] .sample {
    font-family: "Naiova Noto Sans Thai Looped", sans-serif;
}

.font-choice [data-font="loopless"] .sample {
    font-family: "Naiova Noto Sans Thai", sans-serif;
}
.site-footer code { font-size: .95em; word-break: break-all; }

/* --- controls ------------------------------------------------------------ */

/* Wrapping, not shrinking. The button carries a word that cannot be made narrower —
   "Rechercher" is half again as long as "Suchen" — and its width also grows with the
   reader's system font scale, which Android users raise more often than desktop users do.
   Any fixed breakpoint guesses at both. Letting the row wrap removes the question: while
   there is room the two sit side by side, and when there is not the button moves under the
   field and fills the width. Reported from a phone where the button was cut off at the
   screen edge in every language. */
.search { display: flex; flex-wrap: wrap; gap: .5rem; }

.search input {
    /* The large grow factor keeps the field, not the button, absorbing the free space on a
       wide row; the 14rem basis is what decides when there is no longer room for both. */
    flex: 999 1 14rem;
    min-width: 0;
    height: var(--naiova-control-height);
    padding: 0 .85rem;
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-md);
    background: var(--naiova-surface);
    color: inherit;
    /* Never below 1rem: iOS Safari zooms the viewport on focus for smaller text. */
    font-size: 1rem;
}

.search input::placeholder { color: var(--naiova-text-muted); }

.search button {
    /* Grows only once it is alone on its line, where it spans the width. */
    flex: 1 1 auto;
    height: var(--naiova-control-height);
    padding: 0 1.15rem;
    border: 1px solid var(--naiova-brand);
    border-radius: var(--naiova-radius-md);
    background: var(--naiova-brand);
    color: #fff;
    font-weight: 650;
    cursor: pointer;
    transition: background-color 140ms ease, border-color 140ms ease;
}

.search button:hover {
    background: var(--naiova-brand-strong);
    border-color: var(--naiova-brand-strong);
}

.search--hero { margin: 1.5rem 0 1.25rem; }
.search--hero input,
.search--hero button { height: 3.1rem; }
.search--hero input { font-size: 1.1rem; }

.intro h1 {
    margin: .5rem 0 .35rem;
    font-size: clamp(1.75rem, 5vw, 2.25rem);
    font-weight: 700;
    letter-spacing: -.01em;
}

.intro p.lede {
    margin: 0;
    color: var(--naiova-text-muted);
    font-size: 1.05rem;
    max-width: 38rem;
}

.examples {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: .45rem;
    align-items: center;
}

.examples > li:first-child {
    color: var(--naiova-text-muted);
    font-size: .85rem;
}

.examples a {
    display: inline-block;
    padding: .3rem .8rem;
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-md);
    background: var(--naiova-surface);
    color: var(--naiova-text);
    text-decoration: none;
    font-size: .95rem;
}

.examples a:hover {
    border-color: color-mix(in srgb, var(--naiova-brand) 30%, var(--naiova-border));
    color: var(--naiova-brand-strong);
}

.examples .thai { font-size: 1.05rem; }

/* --- Thai and romanization ----------------------------------------------- */

.thai {
    font-family: var(--naiova-font-thai);
    /*
        Thai has no capitals and a shorter x-height relative to Latin, so it is set a
        step larger, with extra line height for the stacked vowel and tone marks.
    */
    font-size: 1.35em;
    line-height: 1.5;
    font-weight: 400;
}

/*
    Pronunciation carries Naiova's accent orange: it is the one piece of information
    this product is unusual for, and the accent is reserved for it.
*/
.roman {
    color: var(--naiova-accent-strong);
    font-variant-ligatures: none;
}

/* --- page frame ---------------------------------------------------------- */

/*
    One column by default. At wide viewports the recent-searches rail moves alongside
    the content; below that it follows underneath, which is why it is a sibling of the
    content rather than nested in it.
*/
.page {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2rem;
    align-items: start;
}

/* --- search results ------------------------------------------------------ */

.results-heading {
    font-size: .9rem;
    font-weight: 400;
    color: var(--naiova-text-muted);
    margin: 0 0 .5rem;
}

.results { list-style: none; margin: 0; padding: 0; }

.result {
    border-bottom: 1px solid var(--naiova-border);
    padding: .9rem 0;
}

.result a.result-link {
    display: block;
    text-decoration: none;
    color: inherit;
}

.result a.result-link:hover .thai { text-decoration: underline; }

.result .headword {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .15rem .6rem;
}

.result .roman { font-size: 1rem; }
.result .gloss { margin: .15rem 0 0; color: var(--naiova-text-muted); }

.result .pos {
    color: var(--naiova-text-muted);
    font-size: .85rem;
    font-style: italic;
}

/*
    The strongest match is marked with Naiova's brand tint, the same treatment the
    application uses for an active navigation item. Light on purpose: a reference tool
    should not shout, and the reason line already says why it leads.
*/
.result--top {
    background: color-mix(in srgb, var(--naiova-brand) 7%, var(--naiova-surface));
    border-left: 3px solid var(--naiova-brand);
    border-radius: 0 var(--naiova-radius-md) var(--naiova-radius-md) 0;
    padding-left: .85rem;
    margin-left: -.85rem;
}

.why {
    display: inline-block;
    margin-top: .3rem;
    font-size: .78rem;
    color: var(--naiova-text-muted);
}

.why::before {
    content: "";
    display: inline-block;
    width: .35rem;
    height: .35rem;
    margin-right: .4rem;
    border-radius: 50%;
    background: var(--naiova-border);
    vertical-align: .1em;
}

.result--top .why::before { background: var(--naiova-brand); }

.more { margin: 1.25rem 0 0; font-size: .95rem; }

.empty {
    margin: 1.5rem 0;
    padding: 1.1rem 1.2rem;
    background: var(--naiova-surface);
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-md);
    box-shadow: var(--naiova-surface-shadow);
}

.empty p { margin: 0 0 .4rem; }
.empty .examples { margin: .15rem 0 .75rem; }
.empty p:last-child { margin-bottom: 0; }

/* --- recent searches ----------------------------------------------------- */

.recent {
    padding: 1rem 1.1rem;
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-md);
    background: var(--naiova-surface);
    box-shadow: var(--naiova-surface-shadow);
}

.recent h2 {
    margin: 0 0 .6rem;
    color: var(--naiova-brand-strong);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
}

.recent ul { list-style: none; margin: 0; padding: 0; }

.recent li + li {
    margin-top: .1rem;
    border-top: 1px solid var(--naiova-surface-muted);
    padding-top: .1rem;
}

.recent a {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .1rem .5rem;
    padding: .4rem .45rem;
    margin: 0 -.45rem;
    border-radius: var(--naiova-radius-sm);
    text-decoration: none;
    color: var(--naiova-text);
}

.recent a:hover { background: var(--naiova-surface-muted); }
.recent .thai { font-size: 1.15em; }
.recent .roman { font-size: .85rem; }

/* A button, because clearing changes state; styled as a link, because it is minor. */
.linkish {
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    text-decoration: underline;
}

.recent__clear {
    margin-top: .7rem;
    color: var(--naiova-text-muted);
    font-size: .78rem;
}

.recent__clear:hover { color: var(--naiova-text); }

/* --- word page ----------------------------------------------------------- */

.entry + .entry {
    margin-top: 2.5rem;
    border-top: 1px solid var(--naiova-border);
    padding-top: 1.5rem;
}

.entry-head { margin-bottom: 1.5rem; }

.entry-head h1 {
    margin: 0;
    font-family: var(--naiova-font-thai);
    font-size: clamp(2.4rem, 11vw, 3.4rem);
    font-weight: 400;
    line-height: 1.35;
    /* Thai descenders and tone marks need room at display sizes. */
    padding: .1em 0;
}

.entry-head .pronunciation {
    margin: .1rem 0 0;
    color: var(--naiova-accent-strong);
    font-size: clamp(1.15rem, 4.5vw, 1.4rem);
}

.entry-head .pos-summary {
    margin: .45rem 0 0;
    color: var(--naiova-text-muted);
    font-style: italic;
}

.senses { list-style: none; margin: 0; padding: 0; }
.sense { padding: 0 0 1.4rem; }

.sense + .sense {
    border-top: 1px solid var(--naiova-border);
    padding-top: 1.3rem;
}

.sense-head {
    display: flex;
    align-items: baseline;
    gap: .55rem;
    margin: 0 0 .5rem;
    font-size: 1rem;
    font-weight: 400;
}

.sense-number {
    flex: 0 0 auto;
    min-width: 1.5rem;
    color: var(--naiova-text-muted);
    font-variant-numeric: tabular-nums;
}

.sense-head .pos { font-style: italic; color: var(--naiova-text-muted); }

/*
    One language, so no language label: the meanings stand on their own line under the
    sense. Catalog records are separated by a middot rather than a comma, because a single
    record may itself contain commas or semicolons ("front; anterior to the back").
*/
.meanings {
    list-style: none;
    margin: 0;
    padding: 0;
    display: inline;
    font-size: 1.05rem;
}

.meanings li { display: inline; }

.meanings li + li::before {
    content: " · ";
    color: var(--naiova-text-muted);
}

.definition {
    margin: .6rem 0 0;
    padding-left: .8rem;
    border-left: 2px solid var(--naiova-border);
    color: var(--naiova-text-muted);
    font-size: .95rem;
}

/* The label carries the whole warning, so it is the part that must read as an aside:
   quieter than the definition it introduces, never louder. */
.definition-language {
    color: var(--naiova-text-muted);
    font-size: .85em;
    font-style: normal;
    opacity: .85;
}

.definition-language::after { content: " "; }

/* Footer links: present on every page, quiet enough not to compete with the dictionary. */
.legal-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0 1.1rem;
    margin-top: .5rem;
}

.legal-links a {
    color: var(--naiova-text-muted);
    font-size: .88rem;
}

/* Legal pages are prose, so they get a reading measure rather than the full width. */
.legal {
    max-width: 44rem;
}

.legal h2 {
    margin: 1.8rem 0 .4rem;
    font-size: 1.05rem;
}

/* The prescribed attribution: set apart so it is visibly a quotation of required
   wording rather than the site's own prose. */
.attribution {
    margin: .8rem 0 1.2rem;
    padding: .8rem 1rem;
    border-left: 3px solid var(--naiova-accent);
    background: var(--naiova-surface);
}

.attribution p {
    margin: 0 0 .4rem;
    font-size: .95rem;
}

.attribution p:last-child {
    margin-bottom: 0;
    color: var(--naiova-text-muted);
}

.licence-files {
    margin: 0 0 1rem;
    padding-left: 1.2rem;
}

.legal p,
.legal address {
    margin: 0 0 .7rem;
    line-height: 1.65;
    font-style: normal;
}

.note,
.ambiguity {
    margin: 1.5rem 0 0;
    padding: .85rem 1rem;
    border: 1px solid var(--naiova-border);
    border-radius: var(--naiova-radius-md);
    background: var(--naiova-surface);
    color: var(--naiova-text-muted);
    font-size: .88rem;
}

.note p { margin: 0; }

.ambiguity {
    margin: 0 0 1.5rem;
    background: color-mix(in srgb, var(--naiova-brand) 7%, var(--naiova-surface));
    color: var(--naiova-text);
    font-size: .92rem;
}

/* --- wider screens ------------------------------------------------------- */

@media (min-width: 40rem) {
    main { padding: 2.5rem 0 4rem; }
}

@media (min-width: 60rem) {
    /*
        Enough room for the recent-lookups rail to sit beside the content. The :not([hidden])
        matters: the rail is always in the markup and only unhidden once the script finds
        something to show, so matching on its mere presence would reserve a column that
        stays empty for every first-time reader.
    */
    .page:has(> .recent:not([hidden])) {
        grid-template-columns: minmax(0, 1fr) 15rem;
        gap: 2.5rem;
    }

    .page > .recent {
        position: sticky;
        top: 1.5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

/* --- result groups -------------------------------------------------------- */

/*
    A Latin-script query can mean a pronunciation or a meaning, so results are grouped
    and each group says which question it answers. Pronunciation leads: identifying a
    word you heard is what this dictionary is for.
*/
.group + .group { margin-top: 2rem; }

.group-heading {
    margin: 0 0 .4rem;
    color: var(--naiova-brand-strong);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
}

/* Narrowing after the search, never a mode before it. */
.narrow {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem 1rem;
    margin: 0 0 1.25rem;
    font-size: .88rem;
}

/* The other reading of what was typed, offered rather than merged into the list. */
.other-reading {
    margin: 0 0 1.25rem;
    font-size: .95rem;
}

/* The parts that differ, named. Never a score. */
.why-detail { color: var(--naiova-text-muted); }
