/* Dari — ink, paper, and a bridge.
   ---------------------------------------------------------------------------
   The identity is editorial, not dashboard. Three ideas carry it:

   1. INK ON PAPER. Warm neutrals, never the cold slate-and-blue of a data app.
      Dark mode is ink; light mode is book paper, not white.

   2. THE TRANSLATION IS THE HERO. It is set in a serif, at size, like a
      printed line — because it is a piece of language, not a field value.
      Chrome stays sans-serif so the two never compete.

   3. THE BRIDGE. 다리 means bridge. The direction bar is an actual span with
      two piers, and the arc recurs as the app's one ornament.

   Language accents (js/theme.js) set --lang-accent and the --motif-* set.
   They are additions: a colour and a texture. The bones above never move.
   --------------------------------------------------------------------------- */

/* ---- Palette -------------------------------------------------------------
   Cream is the default look, not a light-mode afterthought. Dari is paper: a
   warm off-white page you read a translation off. The dark variant is a
   NEUTRAL ink grey - deliberately not brown, which read as muddy.

   Appearance is a user setting (cream / ink / auto), not a system guess, so
   the app looks the way it was designed regardless of OS dark mode.
   ------------------------------------------------------------------------ */

:root, :root[data-theme="cream"] {
  color-scheme: light;

  --bg:        #faf6ea;   /* cream page */
  --bg-deep:   #f2ebd9;   /* deckle edge */
  --surface:   #fffdf7;
  --surface-2: #f5efe1;
  --line:      #e2d8c2;
  --line-soft: #ece4d3;
  --text:      #23201a;
  --muted-solid: #6e6453;

  --brass:      #8a6410;
  --brass-deep: #6d4e08;

  --warn:      #8a5a12;
  --warn-soft: #f8ead0;
  --danger:    #a8342a;
  --danger-soft: #f9e2df;
}

:root[data-theme="ink"] {
  color-scheme: dark;

  --bg:        #16181c;   /* neutral ink, no brown */
  --bg-deep:   #0f1114;
  --surface:   #1e2126;
  --surface-2: #262a30;
  --line:      #333940;
  --line-soft: #272c32;
  --text:      #edeef0;
  --muted-solid: #98a0ab;

  --brass:      #d9a441;
  --brass-deep: #a87c26;

  --warn:      #e0a355;
  --warn-soft: #2d2717;
  --danger:    #e06b5c;
  --danger-soft: #2c1917;
}

/* "Auto" follows the OS, but still uses the two palettes above. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    color-scheme: dark;
    --bg: #16181c; --bg-deep: #0f1114; --surface: #1e2126;
    --surface-2: #262a30; --line: #333940; --line-soft: #272c32;
    --text: #edeef0; --muted-solid: #98a0ab;
    --brass: #d9a441; --brass-deep: #a87c26;
      --warn: #e0a355; --warn-soft: #2d2717;
    --danger: #e06b5c; --danger-soft: #2c1917;
  }
}

:root {
  --lang-accent:       var(--brass);
  --lang-accent-light: var(--brass);

  /* Set by js/theme.js from the motif in js/culture.js. Three weights of one
     drawn ornament: a band, a soft fill, and a watermark. */
  --motif-band:  none;
  --motif-soft:  none;
  --motif-ghost: none;

  --radius:    10px;
  --radius-lg: 16px;
  --nav-h:     62px;

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
           "Nanum Myeongjo", "Yu Mincho", "Songti SC", serif;
  --sans: system-ui, -apple-system, "Segoe UI", "Malgun Gothic",
          "Apple SD Gothic Neo", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.55 var(--sans);
  overscroll-behavior-y: none;
  -webkit-font-smoothing: antialiased;
}

body {
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  min-height: 100vh;
  position: relative;
}

/* A wash of the language's colour at the top of the page. Colour only - the
   ornament is drawn where it can be recognised as ornament, and a motif
   tiled across the whole page is just noise behind the text. */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto 0;
  height: 320px;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--lang-accent) 9%, transparent) 0%,
    transparent 100%);
}

main, header, nav { position: relative; z-index: 1; }

/* ---------- masthead ---------- */

header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
  backdrop-filter: blur(14px) saturate(1.1);
  border-bottom: 1px solid var(--line-soft);
  padding: 12px 16px calc(12px + env(safe-area-inset-top, 0px));
  display: flex;
  align-items: baseline;
  gap: 10px;
}

header h1 {
  font-family: var(--serif);
  font-size: 22px;
  margin: 0;
  font-weight: 500;
  letter-spacing: .01em;
}

/* The 다리 in the wordmark carries the language accent — the one place the
   current language touches the brand, and only as a tint. */
header .brand-ko {
  color: var(--lang-accent);
  font-weight: 500;
  margin-left: 2px;
}

/* The ornament band on the masthead's edge, like the printed tape on a
   bookbinding. This is the piece that has to be seen from across the room:
   seigaiha waves for Japanese, kranok flames for Thai, oak leaves for
   German. 16px is enough for the drawing to read as itself. */
header::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 16px;
  background-image: var(--motif-band);
  background-repeat: repeat-x;
  background-position: left bottom;
  background-size: auto 16px;
  border-bottom: 1px solid color-mix(in srgb, var(--lang-accent) 30%, transparent);
}

header .spacer { flex: 1; }

/* Settings deserves its own control - it was previously reachable only by
   clicking the model badge, which nobody would guess. */
header .icon-btn {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted-solid);
  border-radius: 8px;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  cursor: pointer;
  align-self: center;
  transition: color .15s, border-color .15s;
}
header .icon-btn:hover { color: var(--lang-accent); border-color: var(--lang-accent); }
header .icon-btn svg { width: 18px; height: 18px; }

/* ---------- the language card ----------
   Previously this was a one-line plate naming a colour, which is why the
   "cultural additions" were invisible: naming a nod is not showing one. The
   card now carries the ornament, the greeting, what the language forces you
   to decide, and the etiquette - and every one of those changes when the
   language does. */

.lang-card {
  position: relative;
  border: 1px solid var(--line);
  border-left: 3px solid var(--lang-accent);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  background: var(--surface);
  margin-bottom: 14px;
  overflow: hidden;
}

/* The motif, large and faint, bled off the right edge. Watermark weight, so
   it reads as the paper rather than as content. */
.lang-card::after {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 46%;
  pointer-events: none;
  background-image: var(--motif-ghost);
  background-repeat: repeat;
  background-size: 84px 42px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 75%);
  mask-image: linear-gradient(90deg, transparent, #000 75%);
}

.lang-card > * { position: relative; z-index: 1; }

.lang-plate {
  display: flex; align-items: center; gap: 11px;
  border: 0;
  background: transparent;
  padding: 11px 13px;
}
.lang-plate .swatch {
  width: 42px; height: 42px; border-radius: 8px; flex: 0 0 auto;
  background-color: color-mix(in srgb, var(--lang-accent) 10%, transparent);
  background-image: var(--motif-soft);
  background-repeat: repeat;
  background-size: 42px 21px;   /* one whole tile, not a crop of one */
  background-position: center;
  border: 1px solid color-mix(in srgb, var(--lang-accent) 45%, transparent);
}
.lang-plate .who { font-family: var(--serif); font-size: 15px; font-weight: 500; }
.lang-plate .why { font-size: 11.5px; color: var(--muted-solid); font-style: italic; }

main { padding: 16px; max-width: 720px; margin: 0 auto; }

.panel { display: none; }
.panel.active { display: block; animation: rise .22s ease-out; }

@keyframes rise {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- bottom nav ---------- */

nav {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 30;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  display: flex;
  background: color-mix(in srgb, var(--bg-deep) 94%, transparent);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--line-soft);
}

nav button {
  flex: 1;
  border: 0;
  background: none;
  color: var(--muted-solid);
  font: inherit;
  font-size: 10.5px;
  letter-spacing: .04em;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
  padding: 0;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}

nav button svg { width: 20px; height: 20px; stroke-width: 1.6; }
nav button.active { color: var(--lang-accent); }

/* A short span under the active tab — the bridge, one more time. */
nav button.active::before {
  content: '';
  position: absolute;
  top: 6px;
  width: 26px; height: 6px;
  border-top: 1.5px solid var(--lang-accent);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: .8;
}

/* ---------- controls ---------- */

textarea, input[type="text"], input[type="password"], select {
  width: 100%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 13px 14px;
  font: inherit;
  resize: vertical;
}

textarea {
  min-height: 116px;
  line-height: 1.6;
  font-family: var(--serif);
  font-size: 18px;
}

textarea:focus, input:focus, select:focus {
  outline: none;
  border-color: var(--lang-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lang-accent) 18%, transparent);
}

label.field {
  display: block;
  margin: 18px 0 7px;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted-solid);
  font-weight: 600;
}

button.primary {
  width: 100%;
  padding: 15px;
  border: 0;
  border-radius: var(--radius);
  background: var(--lang-accent);
  color: var(--bg-deep);
  font: inherit;
  font-weight: 650;
  font-size: 15px;
  letter-spacing: .02em;
  cursor: pointer;
  margin-top: 14px;
  transition: filter .15s, transform .08s;
}
button.primary:hover:not(:disabled) { filter: brightness(1.08); }
button.primary:active:not(:disabled) { transform: translateY(1px); }
button.primary:disabled { opacity: .45; cursor: default; }

button.ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 13px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
button.ghost:hover { border-color: var(--lang-accent); color: var(--lang-accent); }

.row { display: flex; gap: 8px; align-items: center; }
.row.wrap { flex-wrap: wrap; }

/* ---------- chips ---------- */

.chips { display: flex; gap: 7px; overflow-x: auto; padding: 2px 0 5px;
         scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }

.chip {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted-solid);
  border-radius: 6px;
  padding: 7px 13px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
  transition: all .15s;
}
.chip:hover { border-color: var(--muted-solid); color: var(--text); }
.chip[aria-pressed="true"] {
  background: color-mix(in srgb, var(--lang-accent) 14%, transparent);
  border-color: var(--lang-accent);
  color: var(--text);
  font-weight: 600;
}

/* ---------- the bridge (direction bar) ---------- */

/* Two piers with a span between them. This is the app's signature element and
   the reason the name is what it is. */
.swap {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px 16px;
  margin-bottom: 12px;
  position: relative;
  overflow: hidden;
}

/* The span: an arc drawn between the two language names. */
.swap::before {
  content: '';
  position: absolute;
  left: 22%; right: 22%;
  top: 11px; height: 20px;
  border-top: 1.5px solid var(--lang-accent);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: .45;
}

/* The deck the piers stand on. */
.swap::after {
  content: '';
  position: absolute;
  left: 16px; right: 16px; bottom: 9px;
  border-bottom: 1px solid var(--line);
}

.swap .lang {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 16px;
  position: relative;
  padding-bottom: 2px;
}
.swap .spacer { flex: 1; }
.swap button {
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--lang-accent);
  border-radius: 50%;
  width: 34px; height: 34px;
  cursor: pointer;
  display: grid; place-items: center;
  z-index: 1;
  transition: transform .25s, border-color .15s;
}
.swap button:hover { border-color: var(--lang-accent); transform: rotate(180deg); }

/* ---------- cards ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 17px;
  margin-top: 14px;
}

.card h3 {
  margin: 0 0 10px;
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted-solid);
  font-weight: 600;
}

/* The translated line, set like print. */
.translation {
  font-family: var(--serif);
  font-size: 27px;
  line-height: 1.4;
  font-weight: 500;
  word-break: keep-all;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  letter-spacing: -.005em;
}
.translation.korean { color: var(--lang-accent-light); }

.romanization {
  margin-top: 9px;
  color: var(--muted-solid);
  font-size: 14.5px;
  font-style: italic;
  font-family: var(--serif);
  word-break: break-word;
  letter-spacing: .01em;
}

.literal {
  color: var(--muted-solid);
  font-size: 14.5px;
  white-space: pre-wrap;
  font-family: var(--serif);
}

/* ---------- notices ---------- */

/* Register warnings are the app's most important output. Given a bar rather
   than a tinted box so they read as a margin note, not an error. */
.warning {
  background: var(--warn-soft);
  border: 0;
  border-left: 3px solid var(--warn);
  color: var(--warn);
  border-radius: 0 8px 8px 0;
  padding: 12px 14px;
  margin-top: 13px;
  font-size: 14px;
  display: flex; gap: 10px; align-items: flex-start;
}
.warning strong { color: var(--warn); }

.banner {
  background: var(--warn-soft);
  border-left: 3px solid var(--warn);
  color: var(--warn);
  border-radius: 0 8px 8px 0;
  padding: 12px 14px;
  font-size: 14px;
  margin-bottom: 14px;
}
.banner a { color: inherit; }

.error {
  background: var(--danger-soft);
  border-left: 3px solid var(--danger);
  color: var(--danger);
  border-radius: 0 8px 8px 0;
  padding: 12px 14px;
  margin-top: 13px;
  font-size: 14px;
}

/* ---------- gloss ---------- */

.gloss { display: flex; flex-wrap: wrap; gap: 7px; }
.gloss-item {
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
  padding: 8px 11px;
  min-width: 0;
}
.gloss-surface {
  font-family: var(--serif);
  font-weight: 500; font-size: 16px;
  color: var(--lang-accent-light);
}
.gloss-roman { font-size: 11.5px; color: var(--muted-solid); font-style: italic; }
.gloss-meaning { font-size: 13px; margin-top: 2px; }
.gloss-note { font-size: 11.5px; color: var(--muted-solid); }

ul.notes { margin: 0; padding-left: 17px; font-size: 14px;
           color: var(--muted-solid); }
ul.notes li { margin: 6px 0; }

.alt { border-top: 1px solid var(--line-soft); padding-top: 11px; margin-top: 11px; }
.alt:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.alt-text {
  font-family: var(--serif); font-size: 17px;
  font-weight: 500; color: var(--lang-accent-light);
}
.alt-note { font-size: 13px; color: var(--muted-solid); }

.actions { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 14px; }

/* ---------- lists ---------- */

.item {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-left: 2px solid var(--lang-accent);
  border-radius: 0 9px 9px 0;
  padding: 12px 14px;
  margin-bottom: 9px;
}
.item .src { font-size: 13px; color: var(--muted-solid); }
.item .dst {
  font-family: var(--serif);
  font-size: 18px; font-weight: 500; margin-top: 3px;
  word-break: keep-all; overflow-wrap: anywhere;
}
.item .rom { font-size: 12.5px; color: var(--muted-solid); font-style: italic; }
.item .meta { font-size: 11.5px; color: var(--muted-solid); margin-top: 7px;
              display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ---------- conversation ---------- */

.turn { display: flex; margin-bottom: 11px; }
.turn.them { justify-content: flex-start; }
.turn.me { justify-content: flex-end; }
.bubble {
  max-width: 86%;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  padding: 12px 14px;
}
.turn.me .bubble {
  background: color-mix(in srgb, var(--lang-accent) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--lang-accent) 35%, transparent);
}
.bubble .orig { font-size: 13px; color: var(--muted-solid); }
.bubble .trans {
  font-family: var(--serif);
  font-size: 19px; font-weight: 500; margin-top: 3px;
  word-break: keep-all; overflow-wrap: anywhere;
}
.bubble .rom { font-size: 12px; color: var(--muted-solid); font-style: italic; }

.mic-row { display: flex; gap: 9px; margin-top: 14px; }
.mic-row button {
  flex: 1; padding: 16px 10px; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--text); font: inherit; font-weight: 600; cursor: pointer;
  transition: all .15s;
}
.mic-row button:hover { border-color: var(--lang-accent); }
.mic-row button.listening {
  background: var(--lang-accent);
  border-color: var(--lang-accent);
  color: var(--bg-deep);
  animation: pulse 1.3s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .7; } }

/* ---------- camera ---------- */

.shot {
  width: 100%; border-radius: var(--radius);
  border: 1px solid var(--line);
  display: block; margin-top: 12px;
}
.drop {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 38px 18px; text-align: center;
  color: var(--muted-solid);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.drop:hover { border-color: var(--lang-accent); color: var(--text); }
.drop strong { font-family: var(--serif); font-size: 17px; font-weight: 500; }

.crop-handle {
  position: absolute;
  width: 12px; height: 12px;
  background: var(--lang-accent);
  border: 2px solid var(--bg);
  border-radius: 50%;
}
.crop-handle::after {
  content: ''; position: absolute;
  left: -16px; top: -16px; right: -16px; bottom: -16px;
}
.crop-handle[data-corner="nw"] { left: -7px;  top: -7px;    cursor: nwse-resize; }
.crop-handle[data-corner="ne"] { right: -7px; top: -7px;    cursor: nesw-resize; }
.crop-handle[data-corner="sw"] { left: -7px;  bottom: -7px; cursor: nesw-resize; }
.crop-handle[data-corner="se"] { right: -7px; bottom: -7px; cursor: nwse-resize; }

/* ---------- misc ---------- */

.empty {
  text-align: center; color: var(--muted-solid);
  padding: 46px 18px; font-size: 15px;
  font-family: var(--serif); font-style: italic;
}

.spinner {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--bg-deep) 40%, transparent);
  border-top-color: var(--bg-deep);
  animation: spin .7s linear infinite; display: inline-block;
  vertical-align: -2px; margin-right: 8px;
}
@keyframes spin { to { transform: rotate(360deg); } }

.hint { font-size: 12.5px; color: var(--muted-solid); margin-top: 6px;
        line-height: 1.5; }

/* A one-line credit for the current language's accent, shown in Settings.
   The nod is explained rather than left as an unexplained colour. */
.lang-credit {
  font-size: 12px;
  color: var(--muted-solid);
  font-style: italic;
  font-family: var(--serif);
  margin-top: 8px;
  padding-left: 11px;
  border-left: 2px solid var(--lang-accent);
}

@media (min-width: 760px) {
  body { padding-bottom: 0; }
  nav {
    position: sticky; top: 0; bottom: auto; height: 54px;
    border-top: 0; border-bottom: 1px solid var(--line-soft);
    max-width: 720px; margin: 0 auto;
    background: transparent; backdrop-filter: none;
  }
  nav button { flex-direction: row; font-size: 13px; gap: 8px; }
  nav button svg { width: 17px; height: 17px; }
  nav button.active::before { display: none; }
  nav button.active {
    border-bottom: 1.5px solid var(--lang-accent);
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ---------- language switching ----------------------------------------
   Accent and motif are custom properties, so a language change is a
   transition rather than a repaint. The panel does a short cross-fade on top
   so the switch reads as deliberate instead of a flicker. */

:root {
  transition: --lang-accent .35s ease, --lang-accent-light .35s ease;
}

.swap, .card, .chip, .lang-plate, .item, button.primary, nav button.active {
  transition: border-color .35s ease, color .35s ease,
              background-color .35s ease;
}

body.lang-changing main { animation: langSwap .42s ease; }
@keyframes langSwap {
  0%   { opacity: 1; transform: none; }
  35%  { opacity: 0; transform: translateY(6px) scale(.995); }
  36%  { opacity: 0; transform: translateY(-6px) scale(.995); }
  100% { opacity: 1; transform: none; }
}

/* The ornament band sweeps in when the language changes - one visual beat
   that says "the app is now speaking something else". */
body.lang-changing header::after { animation: weave .55s ease; }
@keyframes weave {
  from { opacity: 0; transform: scaleX(.2); transform-origin: left; }
  to   { opacity: 1; transform: scaleX(1); transform-origin: left; }
}


/* ---------- what the language brings ---------- */

.culture {
  padding: 0 13px 12px 13px;
  border-top: 1px solid var(--line-soft);
  margin-top: 2px;
  padding-top: 11px;
}

/* The greeting, in the language's own script and at a size that respects it.
   Hangul, Devanagari and Thai all need more line height than Latin does, so
   this is set generously rather than tightly. */
.culture .greeting {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 7px;
}
.culture .greeting .native {
  font-family: var(--serif);
  font-size: 25px;
  line-height: 1.35;
  color: var(--lang-accent);
  font-weight: 500;
}
.culture .greeting .rom {
  font-size: 12.5px; font-style: italic; color: var(--muted-solid);
}
.culture .greeting .gloss {
  font-size: 12.5px; color: var(--muted-solid);
}
.culture .greeting .say {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted-solid);
  border-radius: 999px;
  width: 26px; height: 26px;
  display: inline-grid; place-items: center;
  cursor: pointer; flex: 0 0 auto;
}
.culture .greeting .say:hover { color: var(--lang-accent);
                                border-color: var(--lang-accent); }
.culture .greeting .say svg { width: 13px; height: 13px; }

/* What this language makes you decide that English does not. One sentence,
   and the reason the register chips above look different per language. */
.culture .forces {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted-solid);
  border-left: 2px solid color-mix(in srgb, var(--lang-accent) 40%, transparent);
  padding-left: 9px;
  margin-bottom: 9px;
}

.culture details > summary {
  cursor: pointer;
  font-size: 12.5px;
  color: var(--lang-accent);
  list-style: none;
  display: flex; align-items: center; gap: 6px;
  padding: 2px 0;
}
.culture details > summary::-webkit-details-marker { display: none; }
.culture details > summary::before {
  content: '';
  width: 6px; height: 6px; flex: 0 0 auto;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .18s;
}
.culture details[open] > summary::before { transform: rotate(45deg); }

.culture ul {
  margin: 8px 0 0; padding: 0; list-style: none;
  display: grid; gap: 7px;
}
.culture ul li {
  font-size: 12.8px; line-height: 1.5;
  color: var(--text);
  padding-left: 15px;
  position: relative;
}
.culture ul li::before {
  content: '';
  position: absolute; left: 2px; top: 8px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--lang-accent);
}

/* The pronunciation-source line in Settings. */
.roman-status { display: grid; gap: 3px; }
.roman-status .quality { font-size: 12.5px; color: var(--text); }
.roman-status .detail { font-size: 12px; color: var(--muted-solid);
                        line-height: 1.5; }

/* ---------- language picker ---------- */

.lang-plate {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.lang-plate .lang-plate-text { flex: 1; min-width: 0; }
.lang-plate .chev { width: 18px; height: 18px; color: var(--muted-solid);
                    flex: 0 0 auto; transition: transform .2s; }
.lang-plate[aria-expanded="true"] .chev { transform: rotate(180deg); }

.lang-menu {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  margin: 0 10px 10px;
  max-height: 320px;
  overflow-y: auto;
  padding: 6px;
  animation: rise .18s ease-out;
}
.lang-option {
  display: flex; align-items: center; gap: 11px;
  width: 100%; text-align: left;
  border: 0; background: none; color: var(--text);
  font: inherit; padding: 9px 10px; border-radius: 8px; cursor: pointer;
}
.lang-option:hover { background: var(--surface-2); }
.lang-option[aria-selected="true"] { background: var(--surface-2);
                                     font-weight: 600; }
.lang-option .dot {
  width: 20px; height: 20px; border-radius: 5px; flex: 0 0 auto;
  border: 1px solid currentColor;
}
.lang-option .native { font-family: var(--serif); font-size: 15px; }
.lang-option .en { font-size: 12px; color: var(--muted-solid); }

/* ---------- per-language extra controls ---------- */

/* These are not preferences. In Thai the politeness particle depends on the
   speaker's gender; in Vietnamese the pronouns depend on relative age. Without
   them the sentence is not fully determined, so they are shown prominently
   for the languages that need them and hidden entirely for those that do not. */
.extra-row { margin-bottom: 10px; }
.extra-label {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted-solid); font-weight: 600; margin-bottom: 5px;
  display: flex; align-items: baseline; gap: 7px;
}
.extra-why { font-size: 10.5px; letter-spacing: 0; text-transform: none;
             font-style: italic; opacity: .85; }

/* ---------- right-to-left ---------- */

/* Arabic is not a font change - the whole reading order flips. Only the
   language's own text is mirrored; the English chrome stays as it is. */
[data-rtl="true"] .translation,
[data-rtl="true"] .alt-text,
[data-rtl="true"] .gloss-surface,
[data-rtl="true"] .item .dst,
[data-rtl="true"] .bubble .trans,
[data-rtl="true"] #handOverText {
  direction: rtl;
  text-align: right;
  unicode-bidi: isolate;
}
[data-rtl="true"] textarea[dir="rtl"] { direction: rtl; text-align: right; }

/* ---------- hand-over view ---------- */

/* One line, very large, nothing else. You hand someone your phone and they
   see their own language - not your interface. */
/* Setting an explicit `display` defeats the `hidden` attribute - [hidden]'s
   display:none is only a UA default and loses to any author rule. Without
   this the overlay is permanently open. */
.handover[hidden] { display: none; }

.handover {
  position: fixed; inset: 0; z-index: 100;
  background: var(--bg);
  background-image: var(--motif-ghost);
  background-repeat: repeat-x;
  background-position: center bottom 24px;
  background-size: auto 40px;
  display: grid; place-items: center;
  padding: 26px;
  animation: rise .2s ease-out;
}
.handover-inner { max-width: 680px; text-align: center; }
.handover-text {
  font-family: var(--serif);
  font-size: clamp(30px, 8vw, 62px);
  line-height: 1.28;
  font-weight: 500;
  color: var(--text);
  word-break: keep-all;
  overflow-wrap: anywhere;
}
.handover-rom {
  margin-top: 14px; font-family: var(--serif); font-style: italic;
  font-size: clamp(14px, 3.2vw, 20px); color: var(--muted-solid);
}
.handover-sub {
  margin-top: 22px; font-size: 13px; color: var(--muted-solid);
  border-top: 1px solid var(--line); padding-top: 14px;
}
.handover-close {
  position: absolute; bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  left: 50%; transform: translateX(-50%);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--text); font: inherit; font-size: 15px;
  padding: 12px 34px; border-radius: 999px; cursor: pointer;
}

input[type="range"] { accent-color: var(--lang-accent); }

/* A pinned phrase is one you need constantly - it should be findable at a
   glance, not just first in the list. */
.item.pinned {
  border-left-width: 4px;
  background: color-mix(in srgb, var(--lang-accent) 6%, var(--surface));
}

/* The "remembered" tag on a result that came out of translation memory. It
   earns its place: it explains why that one was instant, and it is the visible
   sign that the app has an offline vocabulary of its own. */
.memory-tag {
  align-self: center;
  border: 1px solid color-mix(in srgb, var(--lang-accent) 35%, transparent);
  color: var(--lang-accent);
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 11px;
  letter-spacing: .02em;
}

/* ---------- numbers and counters ---------- */

/* The two systems side by side, because the whole point is that they are a
   choice and not a detail. */
.number-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0 16px;
}
.number-card {
  border: 1px solid var(--line);
  border-top: 3px solid var(--lang-accent);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 12px 13px;
}
.number-system {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted-solid);
}
.number-word {
  font-family: var(--serif);
  font-size: 26px; line-height: 1.3; margin: 4px 0 2px;
}
.number-roman { font-size: 12px; font-style: italic; color: var(--muted-solid); }
.number-use { font-size: 11.5px; color: var(--muted-solid); margin: 7px 0 8px; }

@media (max-width: 460px) {
  .number-pair { grid-template-columns: 1fr; }
}

.counter-row .counter-head {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
}
.counter-mark {
  font-family: var(--serif); font-size: 19px; color: var(--lang-accent);
}
.counter-label { font-size: 13px; }
.counter-system {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  border-radius: 999px; padding: 1px 8px;
  border: 1px solid var(--line);
  color: var(--muted-solid);
}
/* The two systems are colour-coded, because after a week you stop reading the
   word and start recognising the badge. */
.counter-system.native {
  color: var(--lang-accent);
  border-color: color-mix(in srgb, var(--lang-accent) 45%, transparent);
}
.counter-system.sino {
  color: var(--brass);
  border-color: color-mix(in srgb, var(--brass) 45%, transparent);
}
.counter-form {
  font-family: var(--serif); font-size: 20px; margin-top: 6px;
}
.counter-note {
  font-size: 12px; color: var(--muted-solid); line-height: 1.5;
  margin-top: 5px;
}

/* ---------- offline word lookup ---------- */

.lookup { display: grid; gap: 10px; }
.lookup-row {
  border-left: 2px solid color-mix(in srgb, var(--lang-accent) 40%, transparent);
  padding-left: 11px;
}
.lookup-word { font-family: var(--serif); font-size: 19px; }
.lookup-base { font-size: 13px; color: var(--muted-solid); }
.lookup-senses { font-size: 13px; line-height: 1.55; margin-top: 3px; }
.lookup-pos {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted-solid); margin-right: 5px;
}

/* ---------- paperwork mode ---------- */

.form-fields { display: grid; gap: 14px; }

.form-field {
  border-left: 2px solid color-mix(in srgb, var(--lang-accent) 40%, transparent);
  padding-left: 12px;
}
.form-label {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
}
.form-source {
  font-family: var(--serif); font-size: 17px; color: var(--text);
}
.form-en { font-size: 13px; color: var(--muted-solid); }
.form-req {
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  border-radius: 999px; padding: 1px 7px; border: 1px solid var(--line);
  color: var(--muted-solid);
}
/* Required is the one that matters, so it is the only one that shouts. */
.form-req.required {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}
.form-what { font-size: 13.5px; line-height: 1.55; margin-top: 4px; }
.form-example {
  font-size: 12.5px; color: var(--muted-solid); font-style: italic;
  margin-top: 3px;
}

/* ---------- model picker ---------- */

/* Anchored to the masthead, which is the sticky positioning context, so it
   stays put when the page scrolls under it. */
.model-menu {
  position: absolute;
  top: calc(100% - 4px);
  right: 14px;
  z-index: 40;
  width: min(330px, calc(100vw - 28px));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 14px 34px -14px rgba(0, 0, 0, .3);
  padding: 6px;
  animation: rise .16s ease-out;
}

.model-option {
  display: flex; gap: 9px; align-items: flex-start;
  width: 100%; text-align: left;
  background: transparent; border: 0;
  border-radius: var(--radius);
  padding: 9px 10px;
  cursor: pointer;
  font: inherit;
  color: var(--text);
}
.model-option:hover { background: var(--surface-2); }
.model-option[aria-selected="true"] { background: var(--surface-2); }

.model-tick {
  width: 14px; flex: 0 0 auto;
  color: var(--lang-accent); font-weight: 600;
  line-height: 1.5;
}
.model-text { display: grid; gap: 2px; min-width: 0; }
.model-name { font-size: 13.5px; font-weight: 500; }
.model-note { font-size: 12px; color: var(--muted-solid); line-height: 1.45; }

.model-foot {
  font-size: 11.5px; color: var(--muted-solid); line-height: 1.5;
  border-top: 1px solid var(--line-soft);
  margin-top: 4px; padding: 8px 10px 4px;
}

/* ---------- settings ---------- */

/* Settings used to be one long column of unrelated controls - a voice picker
   above an API key above a backup button - so the three things anyone opens
   it for were buried in the middle. Grouped, and the set-once sections
   folded away. */
#panel-settings { display: grid; gap: 10px; }

.setting-group {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
}

.setting-group > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 15px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.setting-group > summary::-webkit-details-marker { display: none; }

/* The chevron is drawn rather than a glyph, so it rotates rather than
   swapping character and shifting the row. */
.setting-group > summary::after {
  content: '';
  margin-left: auto;
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-right: 1.7px solid var(--muted-solid);
  border-bottom: 1.7px solid var(--muted-solid);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .18s ease;
}
.setting-group[open] > summary::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

.setting-group > summary:hover { background: var(--surface-2); }
.setting-group[open] > summary {
  border-bottom: 1px solid var(--line-soft);
}

.setting-title {
  font-family: var(--serif);
  font-size: 16px;
  font-weight: 500;
}
.setting-sub {
  font-size: 12px;
  color: var(--muted-solid);
}
/* On a narrow screen the subtitle drops under the title rather than being
   squeezed to two words. */
@media (max-width: 460px) {
  .setting-group > summary { flex-wrap: wrap; }
  .setting-sub { flex-basis: 100%; }
  .setting-group > summary::after { order: 2; }
}

.setting-body { padding: 4px 15px 16px; }
.setting-body > .field:first-child { margin-top: 10px; }
.setting-body .actions { margin-top: 10px; }
.setting-body p.hint { margin: 6px 0 0; }

/* A second level, for reference material that is genuinely reference: the
   speech-level explanations belong near the register setting but should not
   be four paragraphs in the way of it. */
.setting-nested {
  margin-top: 14px;
  border-top: 1px solid var(--line-soft);
  padding-top: 10px;
}
.setting-nested > summary {
  cursor: pointer;
  font-size: 12.5px;
  color: var(--lang-accent);
  list-style: none;
  display: flex; align-items: center; gap: 6px;
}
.setting-nested > summary::-webkit-details-marker { display: none; }
.setting-nested > summary::before {
  content: '';
  width: 6px; height: 6px; flex: 0 0 auto;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .18s;
}
.setting-nested[open] > summary::before { transform: rotate(45deg); }

/* ---------- two-line chips ---------- */

/* The speech-level chips carry an English name and the language's own term
   for it. English leads: 해요체 is exactly what a learner cannot read yet,
   on the control that decides whether they are about to be rude. */
.chip-two-line {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  line-height: 1.25;
  padding-top: 7px;
  padding-bottom: 7px;
}
.chip-en { font-size: 13px; }
.chip-native {
  font-size: 11px;
  opacity: .68;
  font-family: var(--serif);
}

/* ---------- bigger touch targets ---------- */

/* The microphone is used one-handed, in the cold, with someone waiting. On a
   touch screen it gets a target you cannot miss. */
@media (pointer: coarse) {
  .mic-row button { min-height: 76px; font-size: 15px; }
  .chip { padding-top: 9px; padding-bottom: 9px; }
  nav button { min-height: 56px; }
}

/* ---------- recent languages ---------- */

.recent-langs {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 0 13px 12px;
}
.recent-lang {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line);
  background: transparent;
  border-radius: 999px;
  padding: 4px 11px 4px 8px;
  font: inherit; font-size: 12.5px;
  color: var(--muted-solid);
  cursor: pointer;
}
.recent-lang:hover { color: var(--text); border-color: var(--lang-accent); }
.recent-lang .dot {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
}

/* ---------- did it work ---------- */

/* Two thumbs on a result. The signal that matters is not "was the grammar
   right" but "did the person understand me", and only he can answer that. */
.verdict { display: inline-flex; gap: 2px; align-self: center; }
.verdict-btn {
  padding: 5px 8px;
  filter: grayscale(1);
  opacity: .5;
  transition: filter .15s, opacity .15s, transform .15s;
}
.verdict-btn:hover { opacity: .9; filter: grayscale(.3); }
.verdict-btn.chosen {
  filter: none;
  opacity: 1;
  transform: scale(1.08);
  border-color: var(--lang-accent);
}

/* ---------- tap a word ---------- */

/* Every word in a translation is tappable when the offline dictionary can
   answer for it. The underline is faint on purpose: it should be findable,
   not shouty, because most of the time you are reading the sentence rather
   than studying it. */
[data-lookupable] .word {
  cursor: pointer;
  border-bottom: 1px dotted color-mix(in srgb, var(--lang-accent) 45%, transparent);
  border-radius: 2px;
  transition: background-color .12s;
}
[data-lookupable] .word:hover {
  background: color-mix(in srgb, var(--lang-accent) 12%, transparent);
}

.word-pop {
  position: absolute;
  z-index: 60;
  max-width: min(320px, calc(100vw - 16px));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 12px 30px -12px rgba(0, 0, 0, .32);
  padding: 11px 13px;
  animation: rise .14s ease-out;
}
.word-pop-head {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  margin-bottom: 5px;
}
.word-pop-word { font-family: var(--serif); font-size: 19px; }
.word-pop-senses { font-size: 13px; line-height: 1.55; }
.word-pop-actions {
  display: flex; gap: 6px; margin-top: 9px;
}

/* The estimate above the Translate button, for the moment you are deciding
   whether a long paragraph is worth it. */
#costHint {
  margin: 0 0 8px;
  font-variant-numeric: tabular-nums;
}

/* ---------- streaming ---------- */

/* A blinking caret while the sentence is still arriving. It is the only
   honest progress indicator here: a spinner says "something is happening",
   this says "here is what it has said so far". */
.streaming .caret {
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--lang-accent);
  animation: caret 1s steps(2, start) infinite;
}
@keyframes caret { to { visibility: hidden; } }

@media (prefers-reduced-motion: reduce) {
  .streaming .caret { animation: none; opacity: .5; }
}
