/* Open Dua — the reviewed design's own stylesheet, complete.
 *
 * Copied VERBATIM from the prototype in ../OpenDua-source-archive/handoff/, with its mount point
 * rewritten from `#od-app` to `.od-app`. Nothing else is changed. This is
 * every authored rule after the token declarations: the form-control reset,
 * the focus treatment, the two-column page grid (`od-cols`), the fluid type,
 * the pointer-target floors, the theme-paired images, every responsive
 * override, the motion, and print.
 *
 * It is authored CSS rather than Dart `@css` on purpose: this layer is what
 * the design was signed off with, and re-expressing it in another syntax is
 * where fidelity dies. An earlier cut of this file started at the "mobile"
 * banner and silently dropped `od-cols` -- the dua page's whole layout -- which
 * is exactly the class of error shipping the file verbatim exists to prevent.
 *
 * Tokens are NOT here: they live in lib/src/core/theme/palette.dart. The
 * `!important`s are load-bearing against the markup's inline styles.
 */

/* everything that used to be monospace: tabular figures hold the columns */
  .od-app pre { font-variant-numeric: tabular-nums; letter-spacing: 0.005em; }
  /* Form controls do not inherit the page font in any browser. Without this
     reset every button relying on inheritance renders in the UA control face
     (Arial), which is outside the brand and invisible at small sizes. */
  button, input, select, textarea { font: inherit; }
  *:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  /* The search field paints its own border, so an outline on the inner input
     drew a second box inside the first. The wrapper takes the focus treatment
     and the input takes none. */
  .od-app .od-search { border: 1px solid var(--rule); }
  .od-app .od-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
  .od-app .od-search input:focus-visible { outline: none; }
  .od-app .od-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 32px; align-items: start; }
  @media (min-width: 900px) {
    .od-app .od-cols { grid-template-columns: minmax(0, 1fr) 320px; gap: 56px; }
    .od-app .od-cols-left { grid-template-columns: 200px minmax(0, 1fr); gap: 48px; }
  }

  /* ── mobile ───────────────────────────────────────────────────────────
   * Mobile first is a hard requirement: most search traffic arrives on a
   * phone, on a single dua page. Type is fluid so the Arabic stays the
   * anchor at every width without ever losing its diacritic headroom.
   */
  .od-app .od-fluid-hero { font-size: clamp(38px, 7.6vw, 68px); font-weight: 250; letter-spacing: -0.04em; line-height: 1.03; }
  .od-app .od-fluid-h1 { font-size: clamp(30px, 6.6vw, 50px); font-weight: 250; letter-spacing: -0.033em; line-height: 1.06; }
  .od-app .od-fluid-h2 { font-size: clamp(24px, 4.4vw, 34px); font-weight: 300; letter-spacing: -0.028em; line-height: 1.18; }
  .od-app .od-fluid-lede { font-size: clamp(17px, 2.2vw, 21px); }
  .od-app .od-fluid-translation { font-size: clamp(18px, 2.4vw, 21px); }
  /* line-height stays 2.3 at every size — it is set from the tallest
     tashkeel stack, not the baseline */
  .od-app .od-fluid-arabic-card { font-size: clamp(26px, 5.6vw, 32px); }

  /* Pointer targets. WCAG 2.5.8 AA wants every target at least 24px; on touch
     surfaces the project's own 44px rule applies. Bare text-link buttons paint
     no box, so without this their hit area collapses to the text box (~16px). */
  .od-app .od-textlink { min-height: 24px; display: inline-flex; align-items: center; }
  @media (max-width: 899px) {
    .od-app .od-textlink { min-height: 44px; }
  }

  /* Theme-paired images. Both variants ship in the markup and CSS picks one, so
     the right lockup renders with JavaScript disabled — a JS-driven swap would
     leave a static crawl showing the wrong one. */
  .od-app .od-on-light { display: block; }
  .od-app .od-on-dark { display: none; }
  [data-theme="dark"] .od-app .od-on-light { display: none; }
  [data-theme="dark"] .od-app .od-on-dark { display: block; }
  .od-app .od-mark-icon { display: none; }

  .od-app .od-drawer { display: none; }
  .od-app .od-menu-btn { display: none; }
  .od-app .od-player-bar { display: none; }
  .od-app .od-translit-inline { display: none; }

  @media (max-width: 899px) {
    /* Touch surface: the project's own 44px minimum applies to every control,
       not just the ones authored with an explicit height. Raising the box is
       safe because these controls paint their own background or none at all. */
    .od-app button, .od-app input, .od-app a[download], .od-app [role="switch"],
    .od-app .od-textlink { min-height: 44px; }
    /* Plain chip links are not covered by the download/text-link selectors,
       and the reading card's inline 32px rule otherwise wins the cascade. */
    .od-app .od-catchip { display: inline-flex; align-items: center; min-height: 44px; }
    .od-app .od-readrow { min-height: 44px !important; }
    .od-app .od-recording-option { min-height: 44px !important; }
    /* The seek target used negative margins to grow over the selector above
       it. Let its 45px hit area participate in the mobile layout instead. */
    .od-app .od-player-bar [role="slider"] { margin-top: 0 !important; margin-bottom: 0 !important; }
    /* these elements set display inline, so the override must be !important */
    .od-app .od-nav-desktop { display: none !important; }
    .od-app .od-menu-btn { display: flex; }
    .od-app .od-drawer { display: block; }
    .od-app .od-translit-inline { display: flex; }
    /* the sidebar player is replaced by a thumb-reachable bottom bar */
    .od-app .od-player-card { display: none !important; }
    .od-app .od-player-bar { display: block; }
    .od-app .od-sticky { position: static !important; }
    .od-app .od-dev-nav {
      display: flex !important; flex-direction: row !important;
      overflow-x: auto; gap: 4px;
      padding-bottom: 8px; margin-bottom: 4px;
      border-bottom: 1px solid var(--rule); scrollbar-width: none;
      position: static !important;
    }
    .od-app .od-dev-nav::-webkit-scrollbar { display: none; }
    .od-app .od-dev-nav > span { display: none !important; }
    .od-app .od-dev-nav button { white-space: nowrap; }

    /* Multi-column grids collapse at the SAME breakpoint as the nav. A 4-column
       table or a 2-column feature grid cannot survive 790px: the tracks get so
       narrow that titles break one word per line. */
    .od-app .od-stack { grid-template-columns: minmax(0, 1fr) !important; gap: 28px !important; }
    .od-app .od-prevnext { grid-template-columns: minmax(0, 1fr) !important; }
    .od-app .od-prevnext > * { text-align: left !important; }
    /* table rows become cards: name on its own line, remaining cells inline below */
    .od-app .od-trow {
      display: flex !important; flex-wrap: wrap; align-items: baseline;
      gap: 6px 14px !important; padding: 16px 20px !important;
    }
    .od-app .od-trow > *:first-child { flex: 1 1 100%; }
    .od-app .od-trow > *:last-child { text-align: left !important; }
    .od-app .od-thead { display: none !important; }

    /* The collection row has four cells (index, title+source, Arabic incipit,
       duration+play). Plain stacking would orphan the index number, so the cells
       are re-placed: index / title / play on row one, incipit spanning row two. */
    .od-app .od-duarow {
      grid-template-columns: 30px minmax(0, 1fr) auto !important;
      gap: 4px 12px !important;
      align-items: start !important;
    }
    .od-app .od-duarow > *:nth-child(1) { grid-area: 1 / 1; padding-top: 4px; }
    .od-app .od-duarow > *:nth-child(2) { grid-area: 1 / 2; }
    .od-app .od-duarow > *:nth-child(4) { grid-area: 1 / 3; }
    .od-app .od-duarow > *:nth-child(3) { grid-area: 2 / 2 / auto / -1; }

    /* only the copy buttons share the row two-up; the ghost actions keep their
       natural width, and the vertical divider is dropped once the row wraps */
    .od-app .od-actions .od-copybtn { flex: 1 1 calc(50% - 4px); justify-content: center; }
    .od-app .od-actions > span { display: none !important; }
  }

  @media (max-width: 719px) {
    .od-app .od-gutter { padding-left: 16px !important; padding-right: 16px !important; }
    .od-app .od-sect { padding-top: 32px !important; padding-bottom: 44px !important; }
    .od-app .od-sect-hero { padding-top: 36px !important; padding-bottom: 48px !important; }
    /* the lockup would fall under its 100px minimum here, so the icon takes over.
       The icon carries its own two colours, so it needs no theme variant. */
    .od-app .od-mark-lockup { display: none !important; }
    .od-app .od-mark-icon { display: block !important; }
  }

  /* ── motion ───────────────────────────────────────────────────────────
   * The reveal is CSS only. Three JS versions of this were built and thrown
   * away: each one hid the section first and depended on an observer, a timer
   * or a scroll event arriving to put it back, and every time some block was
   * left stranded at opacity 0 — a blank region shipped to the reader. An
   * animation cannot strand: it always runs to its end state, so the worst
   * case is that content appears without moving.
   */
  @keyframes od-rise {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: none; }
  }
  .od-app .od-reveal { animation: od-rise 0.45s ease-out both; }
  /* No scroll-driven variant. `animation-timeline: view()` was tried and cut:
     after a route change the timeline did not re-attach, and three fully
     on-screen blocks sat at opacity 0. Every scroll-triggered mechanism tried
     here — IntersectionObserver, timers, scroll listeners, view() — has at some
     point shipped a blank region, because all of them hide content first and
     rely on something arriving to put it back. A plain entrance animation runs
     to its end state unconditionally. It is a page-entrance fade rather than a
     per-section reveal, and that is the right trade for content that must never
     be invisible. */
  .od-app button, .od-app a, .od-app [role="switch"], .od-app [role="slider"] {
    transition: background-color .18s ease-out, border-color .18s ease-out,
                color .18s ease-out, box-shadow .18s ease-out, transform .18s ease-out;
  }
  .od-app .od-press:active { transform: scale(0.95); }
  .od-app .od-fill { transition: width .2s linear; }
  .od-app [role="slider"]:hover .od-fill, .od-app [role="slider"]:focus-visible .od-fill { background: var(--accent-hover); }
  @keyframes od-ring { 0% { box-shadow: 0 0 0 0 var(--ring); } 100% { box-shadow: 0 0 0 14px rgba(0,0,0,0); } }
  .od-app .od-playing { animation: od-ring 1.7s ease-out infinite; }
  @media (prefers-reduced-motion: reduce) {
    .od-app .od-reveal { animation: none; }
    .od-app .od-playing { animation: none; }
    .od-app *, .od-app *::before, .od-app *::after { transition-duration: 0.01ms !important; }
  }

  @media print {
    .od-noprint { display: none !important; }
    .od-app .od-reveal { animation: none; }
    .od-app { --paper: #FFFFFF; --surface: #FFFFFF; }
  }
