/* ─────────────────────────────────────────────────────────────────────
   Tailwind-subset shim for the Papertek Core Editor
   ─────────────────────────────────────────────────────────────────────

   WHY THIS FILE EXISTS

   The editor modules synced from Skriv style their entire UI with
   TailwindCSS utility classes — the floating toolbar is literally
   `class="fixed z-[300] flex items-center gap-0.5 bg-stone-800 rounded"`.
   Skriv ships Tailwind; Leksihjelp does not, and its web app is
   hand-written CSS with no build step for styles.

   Without these declarations the editor does not fail loudly — it renders
   WRONG: `position` stays `static` so the "floating" toolbar lands in the
   page flow (observed 2026-08-12, sitting on top of the footer text),
   `flex` never applies so buttons stack, and the dark pill background is
   simply absent. That is the failure mode this file removes.

   WHY A SHIM RATHER THAN TAILWIND ITSELF

   Adding Tailwind would mean a CSS build step and an npm toolchain for a
   static, dependency-free app — and the Play CDN would reintroduce exactly
   the runtime CDN dependency the export script was just changed to strip.
   The utility set the editor actually uses is bounded (98 classes,
   extracted mechanically from the synced source), so writing them out is
   cheaper and auditable.

   THE STANDING RISK, STATED PLAINLY

   This file is a SUBSET, pinned to what the editor used on 2026-08-12. If
   Skriv adds a utility class the editor did not use before, it will render
   unstyled here and nothing will fail — same silent-wrong mode as above.
   Re-extract after any editor re-sync. Values below are Tailwind v3
   defaults (stone/emerald palettes, standard spacing scale).

   SCOPE / COLLISIONS

   Deliberately global, not scoped to #panel-write: the editor mounts
   modals and toasts on document.body (see shared/dom-helpers.js
   getModalParent()), so an ancestor-scoped shim would miss them.

   Every one of these 98 names was checked against app.css, content.css and
   popup-views.css, and against the app's own markup. Exactly ONE collides:
   `.hidden`. It is kept because the semantics are identical (the app's own
   rules — `#dict-mount .search-clear.hidden`, `#sync-local-note.hidden` —
   are all `display: none`), and verified against the live page: of the 9
   elements carrying class="hidden", 0 were visible. If a future app
   element needs to carry `hidden` while staying visible, that assumption
   breaks — the rule is marked below.
   ───────────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────
   PREFLIGHT SUBSET  (Tailwind is not only utilities — it ships a reset,
   and the editor's markup silently depends on it)

   The toolbar buttons carry `text-white` and nothing else for background,
   because Preflight sets `button { background-color: transparent }`.
   Without it they fell back to the UA's ButtonFace — white glyphs on
   rgb(239,239,239), i.e. invisible. The slash-menu buttons are worse: they
   carry no classes at all and are styled ENTIRELY by Preflight.

   Scoped to the editor's four mount points rather than applied globally,
   because a bare `button { background: transparent }` would strip every
   button in the Leksihjelp app. Verified first that no app button carries
   a Tailwind-style class, so nothing here can reach one.

   The slash-menu selector is a class TRIPLE rather than an id because that
   element has neither an id nor a stable class — see slash-menu.js:17,
   which builds its root from utilities alone and appends it to
   document.body. If the menu ever loses one of these three classes its
   buttons will revert to UA styling; that is the known-fragile seam here.
   ───────────────────────────────────────────────────────────────────── */
/* Both rules are wrapped in :where() so the SCOPE contributes ZERO
   specificity and the whole selector weighs the same as Tailwind's own
   `button { … }` Preflight rule — which is the point: utilities must win
   over the reset.

   Written the obvious way first (`#editor-floating-toolbar button { … }`)
   this broke exactly as Preflight's authors would predict: at (0,1,0,1) it
   outranked `.text-white` at (0,0,1,0), so `color: inherit` won and the
   labels rendered slate-on-stone — a solid dark pill with invisible
   buttons. `font-weight: inherit` was beating `font-bold` the same way,
   silently. */
:where(#editor-floating-toolbar, .skriv-modal-overlay, #toast-container,
       .z-50.w-56.flex-col) :where(*, ::before, ::after) {
  box-sizing: border-box;
}

:where(#editor-floating-toolbar, .skriv-modal-overlay, #toast-container,
       .z-50.w-56.flex-col) button {
  -webkit-appearance: button;
  background-color: transparent;
  background-image: none;
  border: 0 solid;
  margin: 0;
  padding: 0;
  font-family: inherit;
  font-size: 100%;
  font-weight: inherit;
  line-height: inherit;
  color: inherit;
  cursor: pointer;
}

/* Slash-menu rows get their whole look from Preflight + the menu's own
   layout in Skriv; without this they are unpadded, full-bleed and give no
   hover feedback, which reads as "the menu is broken". */
.z-50.w-56.flex-col button {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.375rem 0.875rem;
  text-align: left;
  font-size: 0.875rem;
}
.z-50.w-56.flex-col button:hover { background-color: #f5f5f4; }
.dark .z-50.w-56.flex-col button:hover { background-color: #44403c; }

/* ── layout / display ───────────────────────────────────────────────── */
.block { display: block; }
.inline { display: inline; }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.flex-1 { flex: 1 1 0%; }
.flex-shrink-0 { flex-shrink: 0; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.justify-center { justify-content: center; }
.gap-2 { gap: 0.5rem; }
.gap-3 { gap: 0.75rem; }
.min-w-0 { min-width: 0; }

/* Verified no-op for existing app markup — see SCOPE note in the header.
   Must beat .flex on the slash-menu root, which carries both. */
.hidden { display: none !important; }

/* ── position ───────────────────────────────────────────────────────── */
.fixed { position: fixed; }
.absolute { position: absolute; }
.relative { position: relative; }
.inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
.top-4 { top: 1rem; }
.right-4 { right: 1rem; }
.z-50 { z-index: 50; }
.z-\[300\] { z-index: 300; }

/* ── sizing ─────────────────────────────────────────────────────────── */
.w-4 { width: 1rem; }
.w-5 { width: 1.25rem; }
.w-56 { width: 14rem; }
.w-px { width: 1px; }
.w-full { width: 100%; }
.h-4 { height: 1rem; }
.h-5 { height: 1.25rem; }
.max-w-sm { max-width: 24rem; }
.max-w-md { max-width: 28rem; }
.max-w-xl { max-width: 36rem; }

/* ── spacing ────────────────────────────────────────────────────────── */
.p-4 { padding: 1rem; }
.p-6 { padding: 1.5rem; }
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; }
.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.ml-1 { margin-left: 0.25rem; }
.mt-0\.5 { margin-top: 0.125rem; }
.-mt-0\.5 { margin-top: -0.125rem; }

/* ── typography ─────────────────────────────────────────────────────── */
.text-xs { font-size: 0.75rem; line-height: 1rem; }
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
.text-center { text-align: center; }
.text-left { text-align: left; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }

/* ── colours (Tailwind v3 stone + emerald) ──────────────────────────── */
.text-white { color: #fff; }
.text-stone-400 { color: #a8a29e; }
.text-stone-600 { color: #57534e; }
.text-stone-700 { color: #44403c; }
.text-stone-900 { color: #1c1917; }
.bg-white { background-color: #fff; }
.bg-black\/70 { background-color: rgb(0 0 0 / 0.7); }
.bg-stone-200 { background-color: #e7e5e4; }
.bg-stone-600 { background-color: #57534e; }
.bg-emerald-600 { background-color: #059669; }

/* ── borders ────────────────────────────────────────────────────────── */
.border { border-width: 1px; border-style: solid; }
.border-stone-200 { border-color: #e7e5e4; }
.border-stone-300 { border-color: #d6d3d1; }
.rounded { border-radius: 0.25rem; }
.rounded-lg { border-radius: 0.5rem; }
.rounded-xl { border-radius: 0.75rem; }
.rounded-2xl { border-radius: 1rem; }

/* ── effects ────────────────────────────────────────────────────────── */
.shadow-lg  { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); }
.shadow-xl  { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }
.shadow-2xl { box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); }
.opacity-0 { opacity: 0; }
.opacity-70 { opacity: 0.7; }
.opacity-100 { opacity: 1; }
.cursor-pointer { cursor: pointer; }
.pointer-events-none { pointer-events: none; }
.pointer-events-auto { pointer-events: auto; }
.scale-95 { transform: scale(0.95); }
.scale-100 { transform: scale(1); }
.transition-colors {
  transition-property: color, background-color, border-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-transform {
  transition-property: transform;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.duration-300 { transition-duration: 300ms; }
.ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); }

/* ── interaction states ─────────────────────────────────────────────── */
.hover\:bg-stone-50:hover { background-color: #fafaf9; }
.hover\:bg-stone-300:hover { background-color: #d6d3d1; }
.hover\:bg-emerald-700:hover { background-color: #047857; }
.hover\:text-stone-600:hover { color: #57534e; }
.focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; }
.focus\:border-emerald-500:focus { border-color: #10b981; }
.focus\:ring-2:focus { box-shadow: 0 0 0 2px var(--pk-ring, #10b981); }
.focus\:ring-emerald-500:focus { --pk-ring: #10b981; }

/* ── dark mode (Tailwind CLASS strategy — theme.js toggles .dark on
      <html>, see shared/theme.js:58) ─────────────────────────────────── */
.dark .dark\:bg-stone-700 { background-color: #44403c; }
.dark .dark\:bg-stone-800 { background-color: #292524; }
.dark .dark\:border-stone-700 { border-color: #44403c; }
.dark .dark\:text-stone-100 { color: #f5f5f4; }
.dark .dark\:text-stone-200 { color: #e7e5e4; }
.dark .dark\:text-stone-400 { color: #a8a29e; }
.dark .dark\:hover\:bg-stone-600:hover { background-color: #57534e; }

/* ── second pass ─────────────────────────────────────────────────────
   These 16 were missed by the first extraction, which only read clean
   class="…" attributes and skipped any string containing a ${…}
   interpolation — and the floating toolbar builds its class list exactly
   that way. The symptom was instructive: the toolbar became a correctly
   positioned flex row with NO background and NO rounding, i.e. right
   enough to look intentional. Re-derived by scanning every string literal
   in the synced source, which is what the re-extraction note in the header
   means. ─────────────────────────────────────────────────────────────── */
.bg-stone-800 { background-color: #292524; }
.hover\:bg-stone-600:hover { background-color: #57534e; }
.font-medium { font-weight: 500; }
.italic { font-style: italic; }
.underline { text-decoration-line: underline; }
.select-none { user-select: none; -webkit-user-select: none; }
.gap-0\.5 { gap: 0.125rem; }
.px-1\.5 { padding-left: 0.375rem; padding-right: 0.375rem; }
.w-8 { width: 2rem; }
.h-8 { height: 2rem; }
.rounded-full { border-radius: 9999px; }
.shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
.origin-bottom { transform-origin: bottom; }
.resize { resize: both; }
.duration-150 { transition-duration: 150ms; }
.transition-all {
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

/* ── third pass: word-counter, text-export, special-chars-panel ──────
   Added when those three modules were synced. Re-derived the same way
   (every string literal in the source), which is the routine the header
   asks for after any re-sync — not optional bookkeeping: an unstyled
   utility here shows up as a panel that is invisible or mispositioned
   rather than as an error. ──────────────────────────────────────────── */
.overflow-hidden { overflow: hidden; }
.p-1 { padding: 0.25rem; }
.mb-0\.5 { margin-bottom: 0.125rem; }
.w-7 { width: 1.75rem; }
.h-7 { height: 1.75rem; }
.z-\[200\] { z-index: 200; }
.shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }
.font-serif { font-family: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; }
.leading-tight { line-height: 1.25; }
.transition-opacity {
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
/* word-counter swaps this in when a max-word guidance is exceeded. We pass
   no guidance, so it should never fire — defined anyway, because "styled
   only on the path we happen to use" is how the toolbar ended up
   backgroundless. */
.text-red-600 { color: #dc2626; }
.hover\:bg-stone-100:hover { background-color: #f5f5f4; }
.active\:bg-stone-200:active { background-color: #e7e5e4; }

/* ── the editor's one custom animation ──────────────────────────────── */
@keyframes modal-in {
  from { opacity: 0; transform: scale(0.95) translateY(4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.animate-modal-in { animation: modal-in 150ms cubic-bezier(0, 0, 0.2, 1); }

@media (prefers-reduced-motion: reduce) {
  .animate-modal-in { animation: none; }
  .transition-colors, .transition-transform { transition-duration: 0ms; }
}
