/* ─────────────────────────────────────────────────────────────────
   albanisht brand stylesheet
   Color palette grounded in flag red, antique gold and granite gray
   on a primarily neutral cream field. Source Serif headings, Inter
   body. Loaded after Tailwind so utilities are still available;
   component classes here define the design system.
   ───────────────────────────────────────────────────────────────── */

:root {
  /* Brand colors */
  --c-primary:       #C8102E;   /* Albanian flag red, slightly deeper */
  --c-primary-dark:  #8B0E1F;   /* hover, focused text */
  --c-secondary:     #1A1A1A;   /* rich near-black, not pure 000 */
  --c-accent:        #C5A03A;   /* muted antique gold */

  /* Surfaces and text */
  --c-bg:            #FAFAF7;   /* warm off-white, slightly cream */
  --c-bg-elevated:   #FFFFFF;
  /* --c-card is the opaque surface for header + nav dropdown + offline
     cards. Was undefined originally, which made `background: var(--c-card)`
     resolve to transparent — the mobile nav dropdown showed page content
     bleeding through it. Defined now as the elevated white surface so the
     dropdown actually occludes whatever is behind it. */
  --c-card:          #FFFFFF;
  --c-placeholder:   #5F6B7D;   /* 4.9:1 on the pale fields (#F1F5FA), 5.4:1 on white (design audit D12) */
  --c-text-primary:  #1A1A1A;
  --c-text-muted:    #5A5A5A;
  --c-border:        #E5E2DC;   /* warm gray */

  /* Accents for textures and state */
  --c-granite:       #6B7A7F;
  --c-snow:          #F0F2F0;
  --c-evergreen:     #2D4A3E;
  --c-success:       var(--c-evergreen);
  --c-warning:       #B8860B;
  --c-error:         var(--c-primary-dark);

  /* Adriatic / Kosovo-flag inspired blue. Secondary accent introduced
     in the "open blue" pass — additive, not a replacement for the flag
     red which remains the primary brand color. */
  --c-sky:           #3D6BAA;
  --c-sky-dark:      #2A4F85;
  --c-sky-soft:      #E6EDF6;

  /* Typography */
  --font-serif: "Source Serif 4", "EB Garamond", Georgia, "Times New Roman", serif;
  --font-sans:  "Inter", "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono:  "JetBrains Mono", "Source Code Pro", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Layered drop-shadow tokens — give the site a real 3D feel via
     multi-layer shadows. Four shadow ramps from soft (small UI
     elements) to dramatic (hero, translator card). An inset top
     highlight adds a subtle bevel that suggests the surface is lifted
     from the page. */
  --shadow-soft:  0 1px 2px rgba(26,26,26,0.07),
                  0 2px 6px rgba(26,26,26,0.06);
  --shadow-card:  0 2px 5px rgba(26,26,26,0.09),
                  0 8px 20px rgba(26,26,26,0.08),
                  0 24px 48px rgba(26,26,26,0.07);
  --shadow-lift:  0 4px 10px rgba(26,26,26,0.11),
                  0 16px 32px rgba(26,26,26,0.10),
                  0 36px 72px rgba(26,26,26,0.09);
  --shadow-deep:  0 6px 14px rgba(26,26,26,0.13),
                  0 24px 48px rgba(26,26,26,0.12),
                  0 48px 96px rgba(26,26,26,0.10);
  /* Inset top-edge highlight — fake bevel suggesting the card is
     catching ambient light from above. Pairs with the drop shadows. */
  --bevel-top:    inset 0 1px 0 rgba(255,255,255,0.9);
}

/* Base typography */
html {
  background: var(--c-bg);
  color: var(--c-text-primary);
}
body {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  /* Subtle background pattern: topographic contours (right) + network
     graph (left), low-opacity granite on cream. Fixed attachment so it
     doesn't scroll with content. */
  background-color: var(--c-bg);
  background-image: url("/static/bg-pattern.svg");
  background-repeat: no-repeat;
  background-position: center center;
  background-size: cover;
  background-attachment: fixed;
}

h1, h2, h3, .serif {
  font-family: var(--font-serif);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Tap targets: 48pt minimum, 56pt for primary CTAs. Elderly users on
   small touchscreens are the design target. */
.btn { min-height: 48px; min-width: 48px; display: inline-flex; align-items: center; justify-content: center; }
.btn-cta { min-height: 56px; padding-left: 24px; padding-right: 24px; }

/* Reduced motion: kill all transitions and animations. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
}

/* High contrast: deepen borders, strip the warm cream. */
@media (prefers-contrast: more) {
  :root {
    --c-bg:           #FFFFFF;
    --c-text-primary: #000000;
    --c-text-muted:   #000000;
    --c-border:       #000000;
  }
  a, .btn-primary { text-decoration: underline; }
}

/* Focus states: always visible, never suppressed. */
:focus-visible {
  outline: 3px solid var(--c-primary);
  outline-offset: 2px;
}

/* Inputs: 18pt mobile minimum so iOS Safari does not auto-zoom on
   focus. Steps down on viewports wide enough that the soft keyboard
   does not displace the layout. */
.input, textarea.input, input.input {
  font-size: 18px;
  line-height: 1.5;
  background: transparent;
  color: var(--c-text-primary);
}
@media (min-width: 768px) {
  .input, textarea.input, input.input { font-size: 16px; }
}

/* ─── Utility-class overrides for the existing Tailwind utilities the
   templates already use. .bg-card now carries the 3D card treatment:
   subtle white-to-cream gradient + multi-layer shadow. ─── */
.text-primary  { color: var(--c-primary); }
.bg-primary    { background-color: var(--c-primary); }
.border-primary { border-color: var(--c-primary); }
.text-muted    { color: var(--c-text-muted); }
.bg-card       {
  background: linear-gradient(180deg, #FFFFFF 0%, var(--c-bg) 100%);
  box-shadow: var(--shadow-card), var(--bevel-top);
}
.border-default { border-color: var(--c-border); }
.text-accent   { color: var(--c-accent); }
.border-accent { border-color: var(--c-accent); }

/* ─── Buttons ─── */
.btn-primary {
  background: linear-gradient(180deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
  color: #FFFFFF;
  border: 1px solid var(--c-primary-dark);
  font-weight: 600;
  box-shadow:
    0 1px 2px rgba(139, 14, 31, 0.4),
    0 4px 12px rgba(200, 16, 46, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.btn-primary:hover {
  background: linear-gradient(180deg, var(--c-primary-dark) 0%, #6E0B19 100%);
  box-shadow:
    0 2px 4px rgba(139, 14, 31, 0.5),
    0 8px 20px rgba(200, 16, 46, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.btn-primary:active {
  transform: translateY(1px);
  box-shadow:
    0 1px 2px rgba(139, 14, 31, 0.4),
    inset 0 1px 2px rgba(0, 0, 0, 0.15);
}
.btn-primary[disabled] { opacity: 0.55; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  .btn-primary { transition: none; }
}

.btn-ghost {
  background: transparent;
  color: var(--c-text-primary);
  border: 2px solid var(--c-border);
  font-weight: 500;
}
.btn-ghost:hover { border-color: var(--c-text-primary); }

/* ─── Brand mark ─── */
.brand-mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--c-text-primary);
}
/* The mark: Bjeshket, the Alps above the waterline and their reflection as a voice
   (app/static/brand/; the owner's pick, 13 October 2026). The header uses the small cut, 24:22.5. */
.brand-mark .mark {
  display: inline-block;
  width: 34px;
  height: 32px;
}
.brand-mark .wordmark {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 24px;
  letter-spacing: -0.01em;
  color: var(--c-text-primary);
  line-height: 1;
}

/* ─── Hero block (landing page) ─── */
.hero {
  position: relative;
  padding: 96px 24px 128px;
  max-width: 1100px;
  margin: 24px auto 0;
  overflow: hidden;
  /* Stronger gradient depth: cream lifting to faint sky. */
  background: linear-gradient(180deg, #FFFFFF 0%, var(--c-bg) 50%, var(--c-sky-soft) 100%);
  border: 1px solid var(--c-border);
  border-radius: 24px;
  box-shadow: var(--shadow-deep), var(--bevel-top);
}
.hero-headline {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: clamp(32px, 6vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--c-text-primary);
  max-width: 22ch;
}
.hero-sub {
  margin-top: 18px;
  font-family: var(--font-sans);
  font-size: clamp(16px, 2.2vw, 20px);
  line-height: 1.45;
  color: var(--c-text-muted);
  max-width: 38ch;
}
.hero-cta-row {
  margin-top: 32px;
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px;
  align-items: center;
}
.hero-secondary-link {
  color: var(--c-sky);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}
.hero-secondary-link:hover { color: var(--c-sky-dark); }

.hero > * { position: relative; z-index: 1; }

/* ─── Feature cards (landing page) ─── */
.feature-card {
  background: linear-gradient(180deg, #FFFFFF 0%, var(--c-bg) 100%);
  border: 1px solid var(--c-border);
  border-radius: 12px;
  padding: 24px;
  box-shadow: var(--shadow-lift), var(--bevel-top);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.feature-card:hover {
  /* Honor prefers-reduced-motion below — this transitions opt-out. */
  transform: translateY(-2px);
  box-shadow: var(--shadow-deep), var(--bevel-top);
}
@media (prefers-reduced-motion: reduce) {
  .feature-card { transition: none; }
  .feature-card:hover {
    transform: none;
    box-shadow: var(--shadow-lift), var(--bevel-top);
  }
}
.feature-card .icon {
  width: 36px;
  height: 36px;
  color: var(--c-accent);
  margin-bottom: 12px;
}
.feature-card h3 {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
  color: var(--c-text-primary);
}
.feature-card p {
  margin-top: 8px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--c-text-muted);
}

/* ─── Pills used on translator linguistic-notes panel ─── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--c-accent);
  color: var(--c-accent);
  font-size: 13px;
  font-weight: 500;
  background: transparent;
}
.pill[hidden] { display: none; }   /* the notes' register and admirative entries hide when they have nothing to say */

/* ─── Footer ─── */
.brand-footer-tagline {
  font-family: var(--font-serif);
  font-style: italic;
  color: var(--c-text-muted);
}

/* ─── Native <select> + <option> readability.
   Safari iOS and Chrome Android render <option> against the page's
   color-scheme — on dark-mode systems with the default "light dark"
   color-scheme meta, options can appear with dark background and dark
   text. Force light surface + dark text explicitly. ─── */
select.brand-select,
select.brand-select option,
select#dialect-select,
select#dialect-select option {
  background-color: var(--c-bg-elevated);
  color: var(--c-text-primary);
}

/* ─── /translate one-tap direction toggle ───
   Three big segmented buttons. One tap sets the whole translation
   direction. Designed for elderly users on small phones — large tap
   targets (56px min), high-contrast active state, Albanian-first
   labels with English underneath. Stacks vertically on narrow screens
   so each button is full-width and unmissable. */
.lang-toggle {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}
.lang-toggle-btn {
  flex: 1 1 0;
  min-height: 60px;
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: 2px solid var(--c-border);
  border-radius: 12px;
  background: var(--c-bg-elevated);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease,
              box-shadow 0.15s ease, transform 0.1s ease;
}
.lang-toggle-btn .lt-primary {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 700;
  color: var(--c-text-primary);
  line-height: 1.15;
}
.lang-toggle-btn .lt-secondary {
  font-size: 11px;
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: 0.02em;
}
.lang-toggle-btn:hover:not(.is-active) {
  border-color: var(--c-text-primary);
}
.lang-toggle-btn:focus-visible {
  outline: 3px solid var(--c-primary);
  outline-offset: 2px;
}
.lang-toggle-btn.is-active {
  background: linear-gradient(180deg, var(--c-primary) 0%, var(--c-primary-dark) 100%);
  border-color: var(--c-primary-dark);
  box-shadow: 0 2px 6px rgba(200,16,46,0.3),
              inset 0 1px 0 rgba(255,255,255,0.18);
}
.lang-toggle-btn.is-active .lt-primary { color: #FFFFFF; }
.lang-toggle-btn.is-active .lt-secondary { color: rgba(255,255,255,0.85); }
.lang-toggle-btn:active { transform: translateY(1px); }
@media (prefers-reduced-motion: reduce) {
  .lang-toggle-btn { transition: none; }
  .lang-toggle-btn:active { transform: none; }
}
/* Narrow screens: stack the three buttons full-width so each one is a
   big, unmissable tap target. This is the elderly-mobile fix. */
@media (max-width: 640px) {
  .lang-toggle { flex-direction: column; }
  .lang-toggle-btn { width: 100%; min-height: 56px; }
}

/* ─── Nav (Albanian-primary, English secondary) ─── */
.nav-link-bilingual {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
  padding: 6px 10px;
}
.nav-link-bilingual .primary {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 16px;
  color: var(--c-text-primary);
}
.nav-link-bilingual .secondary {
  font-size: 10px;
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: 0.04em;
  margin-top: 1px;
}
.nav-link-bilingual:hover .primary { color: var(--c-primary); }

/* 360px: drop the English secondary line on mobile. Albanian speakers
   are the primary audience on mobile per design direction. */
@media (max-width: 640px) {
  .nav-link-bilingual .secondary { display: none; }
  .nav-link-bilingual .primary   { font-size: 14px; }
  .nav-link-bilingual { padding: 6px 8px; }
}

/* ─── Hero feature-card Albanian subtitles ─── */
.feature-card .sq-sub {
  display: block;
  margin-top: 4px;
  font-style: italic;
  font-size: 14px;
  color: var(--c-text-muted);
  line-height: 1.4;
}

/* ─── Voice mic button on /translate.
   Hidden by default (server doesn't know if browser supports MediaRecorder
   yet); app.js reveals it on feature-detection. ─── */
.btn-mic {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 1px solid var(--c-border);
  background: var(--c-bg-elevated);
  color: var(--c-text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease, color 0.15s ease;
}
.btn-mic:hover { border-color: var(--c-primary); color: var(--c-primary); }
.btn-mic:focus-visible {
  outline: 3px solid var(--c-primary);
  outline-offset: 2px;
}
.btn-mic[hidden] { display: none; }

/* Recording state: red background + pulse on the icon so it's
   unmistakable that the mic is hot. Pulse is GPU-cheap (transform-
   based) and disabled by prefers-reduced-motion. */
.btn-mic.is-recording {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #FFFFFF;
}
.btn-mic.is-recording svg {
  animation: mic-pulse 1.4s ease-in-out infinite;
}
.btn-mic.is-busy {
  background: var(--c-bg);
  color: var(--c-text-muted);
  cursor: wait;
}
/* Speaking (text-to-speech playback) state: sky blue rather than the
   red recording state — playback is calm, recording is hot. */
.btn-mic.is-speaking {
  background: var(--c-sky);
  border-color: var(--c-sky);
  color: #FFFFFF;
}
.btn-mic.is-speaking svg {
  animation: mic-pulse 1.4s ease-in-out infinite;
}
/* Send (app.js shareTranslation): a brief confirmation after copying where there is no share sheet. */
.btn-mic.is-done {
  background: var(--c-sky);
  border-color: var(--c-sky);
  color: #FFFFFF;
}
@media (prefers-reduced-motion: reduce) {
  .btn-mic.is-speaking svg { animation: none; }
}
@keyframes mic-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(0.9); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-mic.is-recording svg { animation: none; }
}

/* Tiny status line that surfaces voice errors / "Transcribing..." */
.voice-status {
  font-size: 12px;
  color: var(--c-text-muted);
  margin-top: 4px;
  min-height: 16px;
}
.voice-status.is-error { color: var(--c-error); }
/* A visitor's daily limit (the translator): a native modal dialog. */
.rl-dialog { width: min(28rem, calc(100% - 32px)); padding: 24px; border: 2px solid var(--c-primary); border-radius: 12px;
  background: var(--c-card); color: var(--c-text-primary); }
.rl-dialog::backdrop { background: rgba(0, 0, 0, .5); }
.rl-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.rl-actions .btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border-radius: 999px; }
/* A photo too poor to read: retake, or use it anyway (app/photo_quality.py). */
.photo-quality-title { display: block; font-weight: 600; }
.photo-quality-hint { display: block; margin-top: 4px; color: var(--c-text-muted); }
.photo-quality-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.photo-quality-actions button { min-height: 44px; padding: 0 16px; border-radius: 999px; font-size: 14px; color: var(--c-text-primary);
  background: var(--c-card); border: 1.5px solid var(--c-border); cursor: pointer; }
.photo-quality-actions button:first-child { background: var(--c-text-primary); color: var(--c-card); border-color: var(--c-text-primary); }
/* Inside the iPhone app a refused microphone links to the app's page in iOS Settings (static/device.js albMic, on
   Bisedo, the translator and /mesazh): a full 44px tap target, in the message's own colour. */
.app-settings-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.25rem;
  vertical-align: middle;
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ─── Language switcher (privacy + terms only) ─── */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 0;
  margin-bottom: 24px;
  font-size: 14px;
}
.lang-switch a {
  color: var(--c-text-muted);
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid var(--c-border);
  background: var(--c-bg-elevated);
}
.lang-switch a:first-child  { border-radius: 6px 0 0 6px; border-right: none; }
.lang-switch a:last-child   { border-radius: 0 6px 6px 0; }
.lang-switch a.active {
  color: var(--c-bg-elevated);
  background: var(--c-text-primary);
  border-color: var(--c-text-primary);
  font-weight: 600;
}
.lang-switch a:hover:not(.active) {
  color: var(--c-text-primary);
  border-color: var(--c-text-primary);
}

/* ─── PWA install CTA + modal ────────────────────────────────────────
   The button stays hidden until pwa.js detects the browser is
   installable (beforeinstallprompt) or the user is on iOS Safari.
   We pair the Albanian label with a smaller English secondary so
   bilingual households (parents + kids) both find it readable.
*/
.btn-install {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.25rem;
  padding: 0.75rem 1.25rem;
  min-height: 56px;
  border-radius: 0.75rem;
  background: linear-gradient(180deg, #FFFFFF 0%, var(--c-bg) 100%);
  color: var(--c-text-primary);
  border: 1px solid var(--c-border);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
  box-shadow: var(--shadow-card), var(--bevel-top);
  transition: transform .12s ease, box-shadow .12s ease;
}
.btn-install:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-deep), var(--bevel-top);
  border-color: var(--c-text-primary);
}
.btn-install:active { transform: translateY(0); }
.btn-install-icon {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--c-primary);
  display: inline-flex;
}
.btn-install-text { display: inline-flex; flex-direction: column; line-height: 1.2; text-align: left; }
.btn-install-text .primary { font-weight: 700; }
.btn-install-text .secondary { font-weight: 400; font-size: 0.8rem; color: var(--c-text-muted); }

/* Footer install link — looks like the other footer links but styled as
   a button under the hood. Hidden by default; pwa.js reveals it. */
.footer-install-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  color: inherit;
  /* like its sibling links, which aren't underlined (launch audit, design L3) */
  text-decoration: none;
}
.footer-install-link:hover { color: var(--c-primary); }

/* Placeholders readable by older eyes (design audit D12): Tailwind's preflight greys them to #9ca3af, 2.3:1 on the
   translator's field. html raises the specificity over the preflight, which loads after this file. */
html input::placeholder, html textarea::placeholder { color: var(--c-placeholder); opacity: 1; }

/* Tab bar (base.html; owner, 2026-10-20): phones and small tablets, where the menu is a button. Above the home's
   docked bar (30), under the open menu's scrim (35). Each tab is the full height of the bar: no target under 48 px. */
.tabbar { display: none; }
@media (max-width: 899.98px) {
  :root:not(.no-tabbar) { --tabbar-h: calc(52px + env(safe-area-inset-bottom)); }
  :root:not(.no-tabbar) body { padding-bottom: var(--tabbar-h); }
  /* What the browser scrolls into view (a focused field, a #delete link, a button) stops above the bar, not under it. */
  :root:not(.no-tabbar) { scroll-padding-bottom: var(--tabbar-h); }
  .tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 31;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    padding: 0 max(4px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(4px, env(safe-area-inset-left));
    background: var(--c-card); border-top: 1px solid var(--c-border);
  }
  .no-tabbar .tabbar, .typing .tabbar { display: none; }
  .tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-width: 0; min-height: 52px; padding: 4px 2px;
    color: var(--c-text-muted); font-size: 11px; line-height: 1.1; font-weight: 500; text-decoration: none; text-align: center;
  }
  .tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tab svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
  .tab[aria-current="page"] { color: var(--c-primary); font-weight: 650; }
  .tab:focus-visible { outline: 2px solid var(--c-primary); outline-offset: -4px; border-radius: 10px; }
}

/* Modal: full-screen overlay on mobile, centered card on desktop. */
.install-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(26, 26, 26, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  overflow-y: auto;
}
@media (min-width: 640px) {
  .install-modal {
    align-items: center;
    padding: 1.5rem;
  }
}
.install-modal[hidden] { display: none; }

.install-modal-inner {
  background: var(--c-bg-elevated);
  color: var(--c-text-primary);
  border-radius: 1rem 1rem 0 0;
  padding: 1.5rem;
  width: 100%;
  max-width: 30rem;
  max-height: 90vh;
  overflow-y: auto;
  position: relative;
  box-shadow: var(--shadow-deep);
}
@media (min-width: 640px) {
  .install-modal-inner { border-radius: 1rem; }
}

.install-modal-close {
  position: absolute;
  top: 0.5rem;
  right: 0.75rem;
  background: none;
  border: none;
  font-size: 1.75rem;
  line-height: 1;
  color: var(--c-text-muted);
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
}
.install-modal-close:hover { color: var(--c-text-primary); }

.install-modal-title {
  font-size: 1.25rem;
  font-weight: 700;
  margin: 0 0 0.75rem 0;
  padding-right: 2rem;
}
.install-modal-title .block { display: block; }

.install-modal-lede {
  margin: 0 0 1.25rem 0;
  line-height: 1.5;
}

.install-modal-platform {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--c-border);
}
.install-modal-platform:first-of-type {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}
.install-modal-step-title {
  font-weight: 700;
  margin: 0 0 0.5rem 0;
  font-size: 0.95rem;
}
.install-modal-steps {
  list-style: decimal;
  padding-left: 1.25rem;
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.5;
}
.install-modal-steps li { margin-bottom: 0.5rem; }
.install-modal-steps li:last-child { margin-bottom: 0; }

.install-modal-done {
  margin-top: 1.25rem;
  width: 100%;
}

/* ─── Audience selector — relational translation UI ─────────────────
   The chip-style summary + collapsible panel. Audience profiles live
   in localStorage; the active one travels with every translate request.
*/
.audience-panel {
  margin: 0 auto;
  max-width: 56rem;
  padding: 0 0.25rem;
}
.audience-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  cursor: pointer;
  list-style: none;
  font-size: 0.85rem;
  color: var(--c-text-muted);
}
.audience-summary::-webkit-details-marker { display: none; }
.audience-label { font-weight: 500; }
.audience-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: 1rem;
  font-size: 0.8rem;
  color: var(--c-text-primary);
}
.audience-chip.is-default { color: var(--c-text-muted); }
.audience-chip-name { font-weight: 600; }
.audience-chip-meta { font-weight: 400; color: var(--c-text-muted); font-size: 0.72rem; }
.audience-summary-hint {
  font-size: 0.72rem;
  color: var(--c-text-muted);
  margin-left: 0.25rem;
}

.audience-body {
  margin-top: 0.75rem;
  padding: 0.75rem;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: 0.625rem;
}

.audience-saved-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px dashed var(--c-border);
  font-size: 0.78rem;
}
.audience-saved-label { color: var(--c-text-muted); font-weight: 500; }
.audience-saved-chips { display: contents; }
.audience-saved-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.55rem;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: 0.5rem;
  font-size: 0.78rem;
  cursor: pointer;
  transition: border-color .12s ease;
}
.audience-saved-chip:hover { border-color: var(--c-primary); }
.audience-saved-chip-remove {
  background: none; border: none; padding: 0 0 0 0.15rem;
  color: var(--c-text-muted); cursor: pointer; font-size: 0.85rem;
}
.audience-saved-chip-remove:hover { color: var(--c-primary); }

.audience-presets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.4rem;
}
.audience-preset {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  padding: 0.55rem 0.7rem;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: 0.5rem;
  cursor: pointer;
  transition: border-color .12s ease, transform .12s ease;
}
.audience-preset:hover {
  border-color: var(--c-primary);
  transform: translateY(-1px);
}
.audience-preset.is-active {
  border-color: var(--c-primary);
  background: var(--c-bg-elevated);
}
.ap-name { font-weight: 600; font-size: 0.85rem; }
.ap-meta { font-size: 0.72rem; color: var(--c-text-muted); margin-top: 0.1rem; }

.audience-custom-form {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--c-border);
}
.audience-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.audience-form-row label {
  display: flex; flex-direction: column;
  font-size: 0.75rem; color: var(--c-text-muted);
  gap: 0.25rem;
}
.audience-form-row input,
.audience-form-row select,
.audience-form-row textarea {
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: 0.4rem;
  padding: 0.4rem 0.5rem;
  font-size: 0.85rem;
  color: var(--c-text-primary);
  font-family: inherit;
}
.audience-form-actions {
  display: flex; align-items: center; gap: 0.75rem;
}
@media (max-width: 640px) {
  .audience-form-row { grid-template-columns: 1fr; }
}

/* ─── Redesigned site header — services as top-level nav ───────────
   Each major surface (Përkthe / Biseda / Dokumente / Certifikuar /
   Vargje) gets its own top-nav slot. Secondary pages (About,
   Benchmark, Privacy, Terms) move to the footer. Mobile collapses
   into a hamburger.
*/
.site-header {
  border-bottom: 1px solid var(--c-border);
  background: var(--c-card);
  position: relative;
  z-index: 50;
}
.site-header-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.85rem 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
@media (min-width: 640px) { .site-header-inner { padding: 0.85rem 1.5rem; } }

.primary-nav {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}
.nav-service {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  padding: 0.4rem 0.7rem;
  border-radius: 0.5rem;
  text-align: center;
  line-height: 1.1;
  transition: background-color .15s ease, color .15s ease;
  text-decoration: none;
  color: var(--c-text-primary);
}
.nav-service .ns-name {
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.005em;
}
.nav-service .ns-en {
  font-size: 0.68rem;
  color: var(--c-text-muted);
  margin-top: 1px;
  letter-spacing: 0.02em;
}
.nav-service:hover {
  background: var(--c-bg-elevated);
}
.nav-service:hover .ns-name { color: var(--c-primary); }
.nav-service.is-active {
  background: var(--c-bg-elevated);
  position: relative;
}
.nav-service.is-active::after {
  content: "";
  position: absolute;
  left: 0.7rem; right: 0.7rem; bottom: 0.15rem;
  height: 2px;
  background: var(--c-primary);
  border-radius: 1px;
}

/* ── Mobile toggle ── */
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--c-border);
  border-radius: 0.45rem;
  padding: 0.45rem 0.55rem;
  cursor: pointer;
  min-width: 44px; min-height: 44px;
  align-items: center; justify-content: center;
}
.nav-toggle:hover { border-color: var(--c-primary); }
.nav-toggle-bars {
  display: inline-flex; flex-direction: column;
  width: 18px; height: 14px;
  justify-content: space-between;
}
.nav-toggle-bars span {
  display: block;
  height: 2px;
  width: 100%;
  background: var(--c-text-primary);
  border-radius: 1px;
  transition: transform .25s ease, opacity .15s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* ── Mobile layout: hamburger + drop-down panel ──
   Up to 899 px: the full header (wordmark, five services, language switch) needs about 820-900 px, and between
   720 and 900 it ran over the wordmark and scrolled the page sideways (launch audit: UX H2, design H1). */
@media (max-width: 899px) {
  .nav-toggle { display: inline-flex; }
  .primary-nav {
    position: absolute;
    top: 100%; left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    /* Explicit opaque background. The CSS-var fallback (#FFFFFF) is
       there as belt-and-suspenders in case --c-card ever gets
       redefined to a transparent value — without it, page content
       bleeds through the open menu, which was the original bug. */
    background: var(--c-card, #FFFFFF);
    /* Sits above .site-header's own z-index (50). The header creates
       a stacking context, but explicit z-index here means the open
       panel will paint above any sibling that grabs its own context. */
    z-index: 60;
    border-bottom: 1px solid var(--c-border);
    box-shadow: 0 8px 24px -10px rgba(0,0,0,0.18);
    padding: 0.5rem 0.75rem 0.8rem;
    transform-origin: top;
    transform: scaleY(0);
    opacity: 0;
    pointer-events: none;
    /* Hidden, not only invisible: its links leave the tab order and the screen reader (UX H4). */
    visibility: hidden;
    transition: transform .2s ease, opacity .2s ease, visibility 0s .2s;
  }
  .primary-nav.is-open {
    transform: scaleY(1);
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transition: transform .2s ease, opacity .2s ease, visibility 0s 0s;
  }
  /* Backdrop scrim: the page under the open menu recedes. It is a layer of the page at z-index 35: above page
     content (the docked bar is 30) and under every header (40 on the home, reading and glass pages, 50 here),
     not a pseudo-element of the menu: inside the transformed panel, position: fixed was fixed to the panel,
     so the "scrim" only greyed the panel itself and never covered the page (launch audit, design H3). A tap on
     it reaches the document and closes the menu (nav.js), and doesn't fall through to a link underneath. */
  body.nav-open::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 35;
    background: rgba(11, 21, 48, 0.42);
  }
  .nav-service {
    flex-direction: row;
    justify-content: flex-start;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.7rem 0.8rem;
    border-radius: 0.5rem;
    text-align: left;
  }
  .nav-service .ns-name { font-size: 1.05rem; }
  .nav-service .ns-en { margin-top: 0; font-size: 0.78rem; }
  .nav-service.is-active::after {
    left: 0.4rem; right: auto; top: 0.7rem; bottom: 0.7rem;
    width: 2px; height: auto;
  }
  body.nav-open { overflow: hidden; }
}

/* The old .nav-link-bilingual is gone from base.html, but other places
   may still use the class — keep the rule intact (no harm). */

/* ─────────────────────────────────────────────────────────────────
   Certified-translation programmatic landing pages
   (one /certified/translation/<slug> page per document type).
   ───────────────────────────────────────────────────────────────── */
.cert-doc-pricing {
  margin: 1.5rem 0 2rem;
  padding: 1rem 1.15rem;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: 0.7rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
}
.cert-doc-price-block { display: flex; flex-direction: column; }
.cert-doc-price-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-text-muted);
}
.cert-doc-price-value {
  margin-top: 0.15rem;
  font-family: var(--font-serif);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--c-text-primary);
}
/* Used in the "Includes" column on flat-fee documents where the value
   is text (e.g. "Diploma + full transcript") rather than a price. */
.cert-doc-price-value-text {
  margin-top: 0.15rem;
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--c-text-primary);
  line-height: 1.25;
}
.cert-doc-price-sub {
  margin-top: 0.15rem;
  font-size: 0.78rem;
  color: var(--c-text-muted);
  line-height: 1.3;
}
.cert-doc-page-note {
  margin: 0.4rem 0 0;
  font-size: 0.82rem;
  color: var(--c-text-muted);
  line-height: 1.45;
  padding: 0.55rem 0.85rem;
  background: var(--c-bg);
  border-left: 2px solid var(--c-border);
  border-radius: 0 0.4rem 0.4rem 0;
}
.cert-doc-cta {
  margin-left: auto;
  padding: 0.75rem 1.4rem;
  font-weight: 600;
}
@media (max-width: 600px) {
  .cert-doc-cta { margin-left: 0; width: 100%; text-align: center; }
}
.cert-doc-section { margin-top: 2.25rem; }
.cert-doc-h2 {
  font-family: var(--font-serif);
  font-weight: 700;
  font-size: 1.35rem;
  color: var(--c-text-primary);
}
.cert-doc-checklist {
  margin-top: 0.65rem;
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}
.cert-doc-checklist li {
  padding-left: 1.5rem;
  position: relative;
}
.cert-doc-checklist li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--c-primary);
  font-weight: 700;
}
.cert-doc-checklist-muted li { color: var(--c-text-muted); }
.cert-doc-checklist-muted li::before { color: var(--c-text-muted); }
.cert-doc-certstatement {
  margin: 0.85rem 0 0;
  padding: 0.9rem 1.05rem;
  background: var(--c-bg-elevated);
  border-left: 3px solid var(--c-primary);
  border-radius: 0.4rem;
  font-style: italic;
  color: var(--c-text-primary);
}
.cert-doc-apostille {
  padding: 0.9rem 1.05rem;
  background: #FFFDF6;
  border: 1px solid #F0E6C5;
  border-radius: 0.6rem;
}
.cert-doc-apostille .cert-doc-h2 { font-size: 1.1rem; }
.cert-doc-bottom-cta {
  margin-top: 2.5rem;
  padding: 1.25rem 1.35rem;
  background: var(--c-bg-elevated);
  border: 1px solid var(--c-border);
  border-radius: 0.7rem;
}


/* ─────────────────────────────────────────────────────────────────
   Offline state
   pwa.js sets `body.is-offline` when navigator.onLine flips false.
   Pages opt in by including a [data-offline-banner] element; this
   rule reveals it and hides its inverse (e.g. the live translate CTA
   on /translate, the mic buttons on /biseda). Banners are bilingual,
   compact, and accessible (role="status" set in markup).
   ───────────────────────────────────────────────────────────────── */

[data-offline-banner] {
  display: none;
  margin: 0.75rem 0 1rem;
  padding: 0.7rem 0.9rem;
  border-radius: 0.6rem;
  background: #FFF7ED;       /* warm amber-50 */
  border: 1px solid #FED7AA; /* amber-200 */
  color: #7C2D12;            /* amber-900 */
  font-size: 0.95rem;
  line-height: 1.45;
}
[data-offline-banner] .ob-sq { font-weight: 600; }
[data-offline-banner] .ob-en {
  display: block;
  font-weight: 400;
  font-size: 0.85rem;
  opacity: 0.85;
  margin-top: 0.15rem;
}
body.is-offline [data-offline-banner] { display: block; }

/* ─── Site language switch (header, every page) ───────────────────────
   One language at a time (app/i18n.py). Plain links, so the switch works
   without JavaScript; each target is at least 44×44px. */
.site-lang {
  display: inline-flex;
  margin-left: auto;
  border: 1px solid var(--c-border);
  border-radius: 0.5rem;
  overflow: hidden;
  flex-shrink: 0;
}
.site-lang a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 0.6rem;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--c-text-muted);
  text-decoration: none;
}
.site-lang a + a { border-left: 1px solid var(--c-border); }
.site-lang a[aria-current="true"] {
  background: var(--c-text-primary);
  color: var(--c-card);
}
.site-lang a:not([aria-current="true"]):hover { color: var(--c-primary); }
@media (min-width: 900px) { .site-lang { order: 3; margin-left: 0.75rem; } }

/* Larger text: the button beside the language switch, and the page's content scaled by it (static/textsize.js).
   The header keeps its size, so its measured breakpoints still hold. */
.text-size { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; margin-left: auto;
  border: 1px solid var(--c-border); border-radius: 0.5rem; background: transparent; color: var(--c-text-primary);
  font-family: inherit; font-size: 0.85rem; font-weight: 600; line-height: 1; letter-spacing: 0.02em; cursor: pointer; flex-shrink: 0; }
.text-size + .site-lang { margin-left: 0.5rem; }
.text-size .text-size-big { font-size: 1.25em; }
.text-size[aria-pressed="true"] { background: var(--c-text-primary); color: var(--c-card); border-color: var(--c-text-primary); }
@media (min-width: 900px) { .text-size { order: 3; margin-left: 0.75rem; } }
html.text-l body:has(.site-header) > main, html.text-l body:has(.site-header) > footer { zoom: 1.18; }

/* Footer links: a full 44px tap target each, wrapping on phones. */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.25rem;
}
.footer-links a,
.footer-links button:not([hidden]) {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.5rem;
}
.footer-links a:hover,
.footer-links button:hover { color: var(--c-primary); }
@media (min-width: 900px) { .primary-nav { margin-left: auto; } }

/* ─── Home = translator (2026-10-12) ──────────────────────────────────
   Phone budget at 390×844: header, direction row, "Kujt i shkruani?"
   chips, text box, Përkthe button and the first line of the translation
   all sit above the fold (tests/e2e/test_home_layout.py). Every
   control is at least 44×44px. */
.nav-service {
  flex-direction: row;
  gap: 0.35rem;
  min-height: 44px;
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 0.95rem;
}
.beta-tag {
  display: inline-block;
  font-family: var(--font-sans, Inter, system-ui, sans-serif);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.1rem 0.35rem;
  border-radius: 0.3rem;
  border: 1px solid currentColor;
  color: var(--c-text-muted);
  vertical-align: middle;
  line-height: 1.2;
}

.tr-wrap { max-width: 72rem; margin: 0 auto; padding: 0.75rem 1rem 1.5rem; }
@media (min-width: 640px) { .tr-wrap { padding: 1.5rem 1.5rem 2rem; } }
.tr-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.tr-h1 { font-size: 1.2rem; font-weight: 700; line-height: 1.2; }
@media (min-width: 640px) { .tr-h1 { font-size: 1.6rem; } }
.tr-clear, .tr-link-btn {
  min-height: 44px; min-width: 44px; padding: 0 0.5rem;
  font-size: 0.875rem; color: var(--c-text-muted); background: none; border: 0; cursor: pointer;
}
.tr-clear:hover, .tr-link-btn:hover { color: var(--c-primary); }

/* Direction: Auto | Shqip → Anglisht | Anglisht → Shqip | ⇄ on one row. */
.tr-dir {
  display: grid;
  grid-template-columns: 1fr 1.2fr 1.2fr 44px;
  gap: 6px;
  margin-top: 0.5rem;
}
.tr-dir .lang-toggle-btn {
  min-height: 44px;
  padding: 4px 6px;
  border-width: 1.5px;
  border-radius: 10px;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--c-text-primary);
  text-align: center;
}
.tr-dir .lang-toggle-btn.is-active { color: #FFFFFF; }
@media (min-width: 640px) { .tr-dir .lang-toggle-btn { font-size: 0.95rem; } }
.tr-swap {
  min-height: 44px; min-width: 44px;
  border: 1.5px solid var(--c-border); border-radius: 10px;
  background: var(--c-bg-elevated); font-size: 1.1rem; cursor: pointer;
}
.tr-swap:hover { border-color: var(--c-text-primary); }

/* "Kujt i shkruani?" chips — always visible, wrap to two rows on phones. */
.aud { margin-top: 0.6rem; }
.aud-row, .aud-more-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.aud-q { font-size: 0.85rem; font-weight: 600; color: var(--c-text-muted); margin-right: 2px; }
.aud-chip {
  min-height: 44px;
  padding: 0 0.8rem;
  border: 1.5px solid var(--c-border);
  border-radius: 999px;
  background: var(--c-bg-elevated);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--c-text-primary);
  cursor: pointer;
}
.aud-chip:hover { border-color: var(--c-text-primary); }
.aud-chip[aria-pressed="true"], .aud-more-btn.is-active {
  background: var(--c-text-primary); border-color: var(--c-text-primary); color: var(--c-card);
}
.aud-chip:focus-visible, .tr-swap:focus-visible { outline: 3px solid var(--c-primary); outline-offset: 2px; }
.aud-more { margin-top: 6px; padding: 0.6rem; border: 1px solid var(--c-border); border-radius: 12px; background: var(--c-card); }
.aud-saved { margin-top: 6px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 0.85rem; }
.aud-saved-item { display: inline-flex; align-items: center; }
.aud-saved-remove { min-width: 44px; min-height: 44px; background: none; border: 0; cursor: pointer; color: var(--c-text-muted); }
.aud-form { margin-top: 0.6rem; display: grid; gap: 0.5rem; grid-template-columns: 1fr; font-size: 0.85rem; }
@media (min-width: 640px) { .aud-form { grid-template-columns: 1fr 1fr; } .aud-form-wide, .aud-form-actions { grid-column: 1 / -1; } }
.aud-form label { display: flex; flex-direction: column; gap: 2px; font-weight: 600; }
.aud-form input, .aud-form select, .aud-form textarea {
  min-height: 44px; border: 1px solid var(--c-border); border-radius: 8px; padding: 0 0.5rem;
  background: var(--c-bg-elevated); font-weight: 400; font-size: 16px;
}
.aud-form textarea { padding: 0.5rem; }
.aud-form-actions { display: flex; gap: 0.5rem; }
.aud-form-actions .btn { min-height: 44px; padding: 0 1rem; border-radius: 8px; }

/* Text box, button, translation: stacked on phones, side by side wide. */
.tr-grid {
  display: grid;
  gap: 0.6rem;
  margin-top: 0.6rem;
  grid-template-columns: 1fr;
  grid-template-areas: "src" "go" "out";
}
@media (min-width: 900px) {
  .tr-grid { grid-template-columns: 1fr 1fr; grid-template-areas: "src out" "go go"; gap: 1rem; }
}
.tr-src { grid-area: src; }
.tr-out { grid-area: out; }
.tr-go { grid-area: go; display: flex; justify-content: center; }
.tr-go-btn { width: 100%; max-width: 22rem; min-height: 48px; border-radius: 10px; }
@media (max-width: 899px) { .tr-go-btn { max-width: none; } }
.tr-card { background: var(--c-card); border: 1px solid var(--c-border); border-radius: 12px; padding: 0.5rem 0.75rem; }
.tr-card-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; min-height: 44px; }
.tr-label { font-size: 0.875rem; font-weight: 600; }
.tr-tools { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
/* Under 360 px the tools wrap under the label: at 320 px they pushed the page sideways (UX H3, WCAG 1.4.10). Only
   there: wider, a wrapped head pushed the answer below the first phone screen (tests/e2e/test_home_layout.py). */
@media (max-width: 359px) { .tr-card-head { flex-wrap: wrap; } .tr-tools { flex-wrap: wrap; justify-content: flex-end; } }
.tr-dialect { min-height: 44px; font-size: 0.875rem; border: 1px solid var(--c-border); border-radius: 8px; padding: 0 0.4rem; }
.tr-textarea { width: 100%; border: 0; outline: 0; resize: none; background: transparent; min-height: 6.5rem; }
@media (min-width: 900px) { .tr-textarea { min-height: 10rem; } }
.tr-output { width: 100%; white-space: pre-wrap; overflow-wrap: break-word; min-height: 3rem; }
@media (min-width: 900px) { .tr-output { min-height: 10rem; } }
.tr-meta { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; min-height: 1rem; }
.tr-doc-link { display: inline-flex; align-items: center; min-height: 44px; font-size: 0.875rem; text-decoration: underline; }
.tr-panel { margin-top: 0.75rem; background: var(--c-card); border: 1px solid var(--c-border); border-radius: 12px; padding: 0.75rem 1rem; }
.tr-panel-summary { cursor: pointer; font-weight: 600; font-size: 0.875rem; min-height: 44px; display: flex; align-items: center; }
.tr-small-btn { min-height: 44px; min-width: 44px; padding: 0 0.9rem; border-radius: 8px; font-size: 0.875rem; }
/* Listen, the voice choice and Share come with a finished translation (app.js setFinal), not as greyed controls on
   an empty card that look broken (design audit D4). */
.tr-out:not(.has-final) #speak-button, .tr-out:not(.has-final) [data-voice-choice], .tr-out:not(.has-final) #share-button,
.tr-out:not(.has-final) .tr-ai-note { display: none; }
/* Recent translations (#tr-recent): one row per translation, the text over its translation, each a 44px target. */
.tr-recent-count { color: var(--c-text-muted); font-weight: 400; }
.tr-recent-note { margin: 0 0 0.5rem; font-size: 0.8125rem; color: var(--c-text-muted); }
.tr-recent-list { list-style: none; margin: 0; padding: 0; }
.tr-recent-list li + li { border-top: 1px solid var(--c-border); }
.tr-recent-item {
  display: grid; gap: 2px; width: 100%; min-height: 44px; padding: 0.5rem 0; text-align: left;
  background: none; border: 0; cursor: pointer; color: inherit; font: inherit;
}
.tr-recent-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tr-recent-src { font-size: 0.875rem; color: var(--c-text-muted); }
.tr-recent-out { font-weight: 600; }
.tr-recent-item:hover .tr-recent-out, .tr-recent-item:focus-visible .tr-recent-out { color: var(--c-primary); }
.tr-recent-clear { margin-top: 0.25rem; text-decoration: underline; }

.home-trust { margin-top: 0.9rem; font-size: 0.85rem; color: var(--c-text-muted); text-align: center; }
.home-trust a { display: inline-flex; align-items: center; min-height: 44px; text-decoration: underline; }
.home-trust a:hover { color: var(--c-primary); }

.home-proof, .home-cards { max-width: 72rem; margin: 0 auto; padding: 1.5rem 1rem; }
@media (min-width: 640px) { .home-proof, .home-cards { padding: 2rem 1.5rem; } }
.home-h2 { font-size: 1.5rem; font-weight: 700; }
.home-proof-lede { margin-top: 0.4rem; color: var(--c-text-muted); font-size: 0.95rem; }
.home-proof-list { margin-top: 1rem; display: grid; gap: 1rem; }
.home-proof-item { background: var(--c-card); border: 1px solid var(--c-border); border-radius: 12px; padding: 1rem; }
.home-proof-label { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--c-text-muted); }
.home-proof-source { margin-top: 0.3rem; font-family: var(--font-serif); font-size: 1.15rem; font-weight: 600; }
.home-proof-pair { margin-top: 0.6rem; display: grid; gap: 0.6rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .home-proof-pair { grid-template-columns: 1fr 1fr; } }
.home-proof-out { border: 1px solid var(--c-border); border-radius: 10px; padding: 0.6rem 0.75rem; }
.home-proof-out.is-ours { border-color: var(--c-primary); }
.home-proof-who { font-size: 0.75rem; font-weight: 700; color: var(--c-text-muted); margin-bottom: 0.2rem; }
.home-proof-note { margin-top: 0.5rem; font-size: 0.85rem; color: var(--c-text-muted); }
.home-proof-more a { display: inline-flex; align-items: center; min-height: 44px; margin-top: 0.5rem; text-decoration: underline; font-weight: 600; }
.home-cards { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .home-cards { grid-template-columns: 1fr 1fr; } }
.home-card { display: block; background: var(--c-card); border: 1px solid var(--c-border); border-radius: 12px; padding: 1rem; text-decoration: none; color: inherit; }
.home-card:hover { border-color: var(--c-text-primary); }
.home-card-title { font-size: 1.15rem; font-weight: 700; display: flex; align-items: center; gap: 0.4rem; }
.home-card p { margin-top: 0.35rem; font-size: 0.9rem; color: var(--c-text-muted); }
.home-card-cta { display: inline-flex; align-items: center; min-height: 44px; margin-top: 0.25rem; font-weight: 600; color: var(--c-primary); }

/* 44px floor for the header brand link and the text-box label (both tap
   targets: the label focuses the text box). */
.brand-mark { min-height: 44px; }
/* Under 360 px (an iPhone SE, or the app at large Dynamic Type: about 314-335 px of page) the mark alone: the
   wordmark ran into the language switch and pushed the menu button off the screen (iOS audit H24, design D10).
   The link keeps its name for a screen reader (aria-label). */
@media (max-width: 369px) { .brand-mark .wordmark { display: none; } }
/* Phones: the mark, its name, larger text, the language switch and the menu need about 411 px at desktop spacing; a
   tighter header (about 362 px) keeps the name clear of the buttons down to 370 px. */
@media (max-width: 429px) {
  .site-header-inner { gap: 0.5rem; padding-left: 0.75rem; padding-right: 0.75rem; }
  .brand-mark { gap: 6px; }
  .brand-mark .wordmark { font-size: 21px; }
  .text-size + .site-lang { margin-left: 0; }
}
/* Under 260 px (a 390 pt iPhone at 200 % page zoom gives about 195): without "Aa" the mark, the language switch and
   the menu fit; with it the menu button sat 27 px off the screen on every page (launch audit, UX L8). At that zoom
   the text is as large as it gets, so "Aa" has nothing left to do. */
@media (max-width: 259px) { .text-size { display: none; } }
.tr-label { display: inline-flex; align-items: center; min-height: 44px; }
/* A translation that belongs to text the user has since edited. */
#target-text.is-stale { opacity: 0.45; }
/* A translation that stopped before it finished (app.js showCut; launch audit H8): kept, visibly unfinished. */
#target-text.is-incomplete { opacity: 0.6; border-style: dashed; }
.tr-cut { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 6px 0 0; font-size: 14px; color: var(--c-text-primary); }
.tr-cut[hidden] { display: none; }
.tr-cut-retry { min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid currentColor; background: transparent;
  color: inherit; font: inherit; font-weight: 600; cursor: pointer; }
/* Përkthe while a translation runs (launch audit H1): a bar moves along its foot; still, without motion. */
.tr-go-btn[aria-busy="true"] { position: relative; overflow: hidden; cursor: progress; }
.tr-go-btn[aria-busy="true"]::after { content: ""; position: absolute; left: 0; bottom: 0; width: 40%; height: 3px;
  background: currentColor; opacity: .6; animation: tr-busy 1.2s ease-in-out infinite; }
@keyframes tr-busy { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
@media (prefers-reduced-motion: reduce) { .tr-go-btn[aria-busy="true"]::after { animation: none; width: 100%; opacity: .35; } }
/* Listen and Send wait for a finished translation (app.js setFinal). */
.btn-mic:disabled { opacity: .4; cursor: default; }
.bench-summary { min-height: 44px; display: flex; align-items: center; }
/* Bisedo shows both languages: English is set in italic, at full
   contrast (dimming it with opacity failed WCAG contrast). */
.bil-en { font-style: italic; }

/* ── 18+ question before Google's voice (voice_age.js) ── */
.voice-age-dialog {
  width: min(460px, calc(100% - 32px)); padding: 22px 22px 18px; border: 1px solid var(--c-border);
  border-radius: 20px; background: var(--c-card); color: var(--c-text-primary);
  box-shadow: 0 30px 80px rgba(11, 21, 48, .25);
}
.voice-age-dialog::backdrop { background: rgba(11, 21, 48, .34); }
.voice-age-dialog h2 { margin: 0 0 10px; font-family: var(--font-serif); font-size: 1.35rem; font-weight: 600; }
.voice-age-dialog p { margin: 0 0 10px; line-height: 1.5; }
.voice-age-dialog .voice-age-note { color: var(--c-text-muted); font-size: .9rem; }
.voice-age-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.voice-age-actions .btn { min-height: 48px; padding: 12px 16px; border-radius: 12px; font-weight: 600; }
@media (min-width: 480px) { .voice-age-actions { flex-direction: row; } .voice-age-actions .btn { flex: 1; } }

/* Woman's / man's voice for Listen (static/voice_choice.js): a small two-way switch beside the button. */
.voice-choice { display: inline-flex; border: 1px solid var(--line, #DCE3EC); border-radius: 999px; overflow: hidden; }
.voice-choice[hidden] { display: none; }
.voice-choice button { min-height: 44px; min-width: 44px; padding: 0 14px; border: 0; background: transparent; font: 500 14px/1 var(--ui, system-ui); color: inherit; cursor: pointer; }   /* 44px: the site's tap-target floor (tests/e2e/test_home_layout.py) */
.voice-choice button[aria-pressed="true"] { background: var(--navy, #0B1530); color: #fff; }
.voice-choice button:focus-visible { outline: 2px solid var(--cobalt, #1B4FA8); outline-offset: -2px; }

/* Skip link (base.html): the first stop for a keyboard, shown only when focused (launch audit, UX L1). */
.skip-link { position: absolute; left: 16px; top: -200px; z-index: 100; display: inline-flex; align-items: center; min-height: 44px;
  padding: 0 18px; border-radius: 999px; background: #0B1530; color: #fff; font-family: inherit; font-size: 16px; font-weight: 600; line-height: 1; text-decoration: none; }   /* in the page's own face (Geist on the D pages) */
.skip-link:focus { top: 12px; }
main:focus { outline: none; }

/* Translating: two quiet lines in the empty output box, gone as the first words arrive (launch audit, design M7). */
.tr-output.is-loading:empty::before, .tr-output.is-loading:empty::after {
  content: ""; display: block; height: 0.72em; margin: 0.36em 0; border-radius: 6px;
  background: linear-gradient(90deg, #EEF2F8 0%, #DDE6F2 40%, #EEF2F8 80%); background-size: 220% 100%;
  animation: tr-shimmer 1.4s ease-in-out infinite; }
.tr-output.is-loading:empty::before { width: 78%; }
.tr-output.is-loading:empty::after { width: 52%; animation-delay: .12s; }
@keyframes tr-shimmer { from { background-position: 100% 0; } to { background-position: -120% 0; } }
@media (prefers-reduced-motion: reduce) { .tr-output.is-loading:empty::before, .tr-output.is-loading:empty::after { animation: none; } }
