/* Wodouh — the app's stylesheet.
 *
 * SPLIT OUT OF app/index.html, and the reason is not file size.
 *
 * Four defects in one week were CSS ordering or direction bugs that a full
 * green suite could not see: a bare `.dk-split{display:grid}` landing after
 * `.screen{display:none}` and un-hiding two screens underneath the active one;
 * a back chevron mirrored on the wrong direction on every screen in both
 * languages; a tab indicator 318px off its tab on an Arabic phone; a hidden
 * heading swallowing the focus target. Every one of them turned on a rule's
 * position relative to another rule hundreds of lines away.
 *
 * The desktop layer's correctness in particular rested on a COMMENT asking a
 * human to keep it last in a 14,000-line file. It is desktop.css now, linked
 * after this file, so "last" is a fact about the page instead of a promise in
 * a comment. That is the whole point of the split.
 *
 * LOAD ORDER IS THE CONTRACT: app.css, then desktop.css. Nothing else.
 */

  /* Self-hosted brand faces (SIL Open Font License 1.1), served from
     /assets/fonts so all three pages share one cached copy. Nothing is
     fetched from a third party. Note this needs http(s): fonts are always
     fetched in CORS mode, so opening these files directly from disk falls
     back to system fonts. */
  @font-face{font-family:'Noto Naskh Arabic';font-style:normal;font-weight:400 700;font-display:swap;
    src:url(../assets/fonts/noto-naskh-arabic-var.woff2) format('woff2');
    unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+08A0-08FF,U+200C-200E,U+2010-2011,U+FB50-FDFF,U+FE70-FEFC;}
  @font-face{font-family:'Nunito';font-style:normal;font-weight:200 1000;font-display:swap;
    src:url(../assets/fonts/nunito-var.woff2) format('woff2');
    unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
  /* THE TYPE SCALE — nine steps, and only nine.
     10.5 · 12 · 13 · 14 · 15 · 16.5 · 19 · 24 · 36
     There were twenty-five, from 10px up: not a scale but an accumulation,
     where 12px and 12.5px both existed for no reason anyone could name and
     the difference between a label and a heading was often half a pixel. That
     is a large part of why hierarchy was hard to read on dense screens — a
     reader cannot use a distinction they cannot see.
     The nine were chosen to sit on the sizes already most used, so most of the
     app did not move; the steps below 12 survive only for letterspaced micro
     labels, which is the one place small is a decision rather than a habit.
     test/type-scale.test.js fails the build on a tenth. */
  :root{
    --teal:#1E6E64; --teal-ink:#134B44; --teal-soft:#DCE9E6;
    /* PAGE, CARD AND LINE ARE THREE STEPS, NOT ONE.
       They used to be almost the same colour: card against page measured
       1.08:1 and the hairline 1.18:1, so a card carried no weight of its own
       and structure was doing its work through spacing and shadow alone. That
       is why dense screens read as a single column. The page drops, the card
       rises to a warm near-white, and the line becomes a line — 1.19:1 and
       1.83:1 now. The warmth is unchanged; only the steps between the greys
       moved. Measured by test/contrast.test.js, which fails the build if any
       of this regresses. */
    --sand:#F1E9D9; --card:#FFFDF6;
    /* --amber was #C9922E, which is 2.45:1 on the page — under the 3:1 that
       WCAG 1.4.11 requires of a colour carrying meaning, and amber is the
       MODAL verdict here: "فاوض" is the most common outcome, so the state a
       low-vision reader could least distinguish was the one they met most.
       Text keeps --amber-ink, which already passed. */
    --amber:#A87822; --amber-bg:#F6EAD2;
    --red:#B4544A; --red-bg:#F3DFDC;
    --green:#478353; --green-bg:#E2EEE2;
    --amber-ink:#8A6114; --green-ink:#33663D; --red-ink:#8E3A31;
  /* SECONDARY TEXT IS A COLOUR, NOT A COLOUR PLUS A FADE.
     Seven rules used to set --ink-2 and then dim it further with opacity —
     .7 on the paste box's placeholder, .65 on an off feature in a plan card,
     .85 on five more. Measured against the surface underneath, those came out
     at 3.15, 2.87 and 4.37 on a card and worse on the page: every one of them
     below AA, on text that is often 12 or 13px.
     They passed the contrast suite because opacity is not a token and the
     suite reads tokens. --ink-2 itself is 5.20 on the page and 6.16 on a card;
     the fade was the whole defect, so the fade is gone rather than the colour
     being darkened to compensate for it. */
    --ink:#2B3230; --ink-2:#5A625F;
    --line:#BEAD88;
    --on-teal:#F1E9D9;
    --page:#E6DCC6;                 /* desktop backdrop behind the phone column */
    /* Luxury here is material, not ornament: warm-tinted light, paper edges,
       and one consistent geometry — never gold, never gloss. */
    --e1:0 1px 2px rgba(74,60,40,.05), 0 1px 1px rgba(74,60,40,.03);
    --e2:0 2px 6px rgba(74,60,40,.055), 0 10px 24px rgba(74,60,40,.045);
    --e3:0 18px 44px rgba(74,60,40,.11);
    --edge:inset 0 1px 0 rgba(255,255,255,.6);
    --shadow:var(--e1);
    --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:22px; --r-2xl:28px;
    --grain:.035;
    /* Motion follows meaning: entrances decelerate, confirmations overshoot,
       positional moves stay neutral. One rhythm for the whole app. */
    --t-fast:160ms; --t:240ms; --t-slow:360ms;
    --ease-out:cubic-bezier(.22,.72,.28,1);
    --ease-spring:cubic-bezier(.22,1.2,.36,1);
    --ease-move:cubic-bezier(.4,0,.2,1);
    --en:'Nunito','Avenir Next Rounded','Segoe UI',-apple-system,'Trebuchet MS',sans-serif;
    --ar:'Noto Naskh Arabic','Geeza Pro','Amiri','Traditional Arabic',serif;
  }
  /* Warm dark theme — for the app's actual peak moment: reading a contract
     in bed the night before signing. Sand becomes the ink, not a grey invert. */
  @media (prefers-color-scheme: dark){
    :root{
      /* The same three-step separation as the light theme, for the same
         reason: card against page was 1.10:1 here and the hairline 1.27:1.
         Teal lightens a little to hold 4.5:1 against the raised card. */
      --teal:#46A695; --teal-ink:#8FCBBE; --teal-soft:#1B2E2B;
      --sand:#0F1513; --card:#212C29;
      --amber:#D9A648; --amber-bg:#2E2618;
      --red:#C86F63; --red-bg:#2E1E1C;
      --green:#6BAE78; --green-bg:#1A2A1E;
      --amber-ink:#E3B865; --green-ink:#87C094; --red-ink:#E0968B;
      --ink:#EDE6D8; --ink-2:#A3ABA6;
      --line:#41504C;
      --on-teal:#0F1614;
      --page:#070B0A;
      --e1:0 1px 2px rgba(0,0,0,.45);
      --e2:0 3px 10px rgba(0,0,0,.42), 0 12px 28px rgba(0,0,0,.34);
      --e3:0 20px 48px rgba(0,0,0,.55);
      --edge:inset 0 1px 0 rgba(255,255,255,.045);
      --shadow:var(--e1);
      --grain:.02;
    }
  }
  :root[data-theme="dark"]{
    --teal:#46A695; --teal-ink:#8FCBBE; --teal-soft:#1B2E2B;
    --sand:#0F1513; --card:#212C29;
    --amber:#D9A648; --amber-bg:#2E2618;
    --red:#C86F63; --red-bg:#2E1E1C;
    --green:#6BAE78; --green-bg:#1A2A1E;
    --amber-ink:#E3B865; --green-ink:#87C094; --red-ink:#E0968B;
    --ink:#EDE6D8; --ink-2:#A3ABA6;
    --line:#41504C;
    --on-teal:#0F1614;
    --page:#070B0A;
    --e1:0 1px 2px rgba(0,0,0,.45);
    --e2:0 3px 10px rgba(0,0,0,.42), 0 12px 28px rgba(0,0,0,.34);
    --e3:0 20px 48px rgba(0,0,0,.55);
    --edge:inset 0 1px 0 rgba(255,255,255,.045);
    --shadow:var(--e1);
    --grain:.02;
  }
  :root[data-theme="light"]{
    --teal:#1E6E64; --teal-ink:#134B44; --teal-soft:#DCE9E6;
    --sand:#F1E9D9; --card:#FFFDF6;
    --amber:#A87822; --amber-bg:#F6EAD2;
    --red:#B4544A; --red-bg:#F3DFDC;
    --green:#478353; --green-bg:#E2EEE2;
    --amber-ink:#8A6114; --green-ink:#33663D; --red-ink:#8E3A31;
    --ink:#2B3230; --ink-2:#5A625F;
    --line:#BEAD88;
    --on-teal:#F1E9D9;
    --page:#E6DCC6;
    --e1:0 1px 2px rgba(74,60,40,.05), 0 1px 1px rgba(74,60,40,.03);
    --e2:0 2px 6px rgba(74,60,40,.055), 0 10px 24px rgba(74,60,40,.045);
    --e3:0 18px 44px rgba(74,60,40,.11);
    --edge:inset 0 1px 0 rgba(255,255,255,.6);
    --shadow:var(--e1);
    --grain:.035;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html[lang="ar"] body{font-family:var(--ar)}
  html[lang="en"] body{font-family:var(--en)}
  body{background:var(--page);color:var(--ink);line-height:1.7;-webkit-font-smoothing:antialiased;
       min-height:100vh;text-rendering:optimizeLegibility;font-kerning:normal}
  html[lang="en"] h1,html[lang="en"] h2,html[lang="en"] h3{letter-spacing:-.014em}
  h1,h2,h3,.verdict,.hello,.ob-title{text-wrap:balance}
  b,strong{font-weight:700}
  html[lang="ar"] b,html[lang="ar"] strong{font-weight:600}
  .app{max-width:440px;margin:0 auto;min-height:100vh;display:flex;flex-direction:column;
       padding:0 18px 28px;background-color:var(--sand);
       background-image:image-set(url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E"));background-size:140px 140px;background-blend-mode:soft-light}
  @supports not (background-image: image-set(url("x"))){
    .app{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E")}
  }
  button{font:inherit;cursor:pointer;border:0;background:none;color:inherit}
  :focus-visible{outline:2px solid var(--teal);outline-offset:3px;border-radius:8px}
  h1:focus,h2:focus{outline:none}
  ::selection{background:color-mix(in srgb, var(--teal) 22%, transparent);color:var(--ink)}
  .app{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
  .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
      clip:rect(0 0 0 0);white-space:nowrap;border:0}
  /* THE DELAY IS THE PART THAT WAS STILL RUNNING.
   *
   * This zeroed animation-duration and said nothing about animation-delay, and
   * the two are not the same switch. Every staggered element in this app is
   * declared `animation: ... both`, so the `both` fill holds the FROM keyframe
   * — opacity:0 — for the whole delay before a duration of any length applies.
   * A reader who asked for less motion therefore got no motion and the wait
   * anyway: the flag cards were invisible for up to 240ms, and the result
   * screen's group sequence below would have made that half a second of blank
   * space for the person least able to tolerate it.
   *
   * Reduced motion means the thing is simply THERE. Zeroing the delay is what
   * makes that true, and it fixes the flag stagger that shipped before this. */
  @media (prefers-reduced-motion: reduce){
    *,*::before,*::after{animation-duration:.01ms !important;animation-delay:0ms !important;
      animation-iteration-count:1 !important;
      transition-duration:.01ms !important;transition-delay:0ms !important;
      scroll-behavior:auto !important}
  }
  /* Between a phone and a laptop: still one column, but framed, so a tablet or
     a narrow window reads as deliberate rather than as a stranded phone page.
     No aside here — there is not room for it beside a 440px column. */
  @media (min-width:600px){
    body{padding:28px 0}
    /* padding-bottom:0 for the same reason as the desktop rule below: once
       there is a visible frame edge, the 28px of padding under the sticky tab
       bar becomes a strip that scrolling content passes through. On a phone
       that strip is below the viewport and nobody ever sees it. */
    .app{min-height:calc(100vh - 56px);border-radius:32px;border:1px solid var(--line);
         box-shadow:var(--e3),var(--edge);padding-bottom:0}
  }


  /* THE FIXED-HEIGHT FRAME IS GONE, and with it a live defect. It used to
     become an 820px scroll box at 1440×900; the end-of-service form is 892px
     tall, so the Calculate button — the only thing on the screen — sat 32px
     below the frame's edge in a container that gives no hint it scrolls. The
     same class of bug was fixed once before for 1280×720 laptops and came
     back at a taller window because the cure was a height, not a page.
     The page scrolls now, which every reader already knows how to do. */

  /* top bar */
  .bar{display:flex;align-items:center;justify-content:space-between;padding:18px 2px 10px}
  .brand{display:flex;align-items:center;gap:10px}
  .brand svg{width:34px;height:34px}
  .brand .name-ar{font-family:var(--ar);font-size:24px;color:var(--teal-ink);line-height:1}
  .brand .name-en{font-family:var(--en);font-size:12px;font-weight:700;letter-spacing:.12em;color:var(--teal);text-transform:uppercase}
  .lang-toggle{font-family:var(--en);font-size:13px;font-weight:700;color:var(--teal);background:var(--teal-soft);border-radius:999px;padding:7px 14px;min-height:44px}
  html[lang="en"] .lang-toggle{font-family:var(--ar);font-size:15px;padding:5px 14px}

  .screen{display:none;flex:1;flex-direction:column}
  .screen.active{display:flex}

  /* home */
  .hello{margin:18px 2px 6px;font-size:24px;color:var(--teal-ink);line-height:1.5}
  .sub{color:var(--ink-2);font-size:15px;margin:0 2px 22px}
  .samples{display:grid;gap:10px}
  .sample{display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:15px 16px;text-align:start;box-shadow:var(--e1),var(--edge);transition:border-color .18s,box-shadow .18s,transform .12s}
  .sample:hover{border-color:var(--teal);box-shadow:var(--e2),var(--edge)}
  .sample .ic{flex:none;width:42px;height:42px;border-radius:12px;background:var(--teal-soft);display:flex;align-items:center;justify-content:center}
  .sample .ic svg{width:22px;height:22px}
  .sample b{display:block;font-size:16.5px;color:var(--ink)}
  .sample span{font-size:13px;color:var(--ink-2)}
  .sample .go{margin-inline-start:auto;color:var(--teal);display:flex}
  .go svg{width:16px;height:16px}
  html[dir="rtl"] .go{transform:scaleX(-1)}
  .or{display:flex;align-items:center;gap:12px;color:var(--ink-2);font-size:13px;margin:20px 0 12px}
  .or::before,.or::after{content:"";flex:1;height:1px;background:var(--line)}
  textarea{width:100%;min-height:120px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px 16px;font:inherit;font-size:14px;color:var(--ink);resize:vertical;line-height:1.8}
  textarea:focus{outline:2px solid var(--teal);outline-offset:0;border-color:transparent}
  /* opacity:1 rather than nothing: Firefox dims placeholders by default, so
     removing the declaration would hand the fade back to the user agent. */
  textarea::placeholder{color:var(--ink-2);opacity:1}
  .paste-hint{font-size:12px;color:var(--ink-2);margin-top:7px;text-align:center}
  .primary{margin-top:14px;width:100%;background:var(--teal);color:var(--on-teal);font-weight:700;font-size:16.5px;
      border-radius:var(--r-lg);padding:16px;transition:opacity .15s,box-shadow .18s;box-shadow:var(--e2)}
  html[lang="en"] .primary{letter-spacing:.005em}
  .primary:hover{box-shadow:var(--e3)}
  .primary:disabled{opacity:.45;cursor:default}
  .disclaimer{margin-top:auto;padding-top:26px;text-align:center;font-size:12px;color:var(--ink-2)}

  /* onboarding */
  /* A FLOOR WITHOUT A CEILING LET THE BUTTON FALL OFF THE SCREEN.
     min-height alone means the card grows with its content, so the tallest
     card — the nationality question, two choice boxes and the longest body
     text — pushed its own "next" button past the bottom of the viewport. It
     was already doing this before the disclosure note was added: measured
     off-screen in English at 390x844, and in both languages at 360x640. The
     reader's only way on was to scroll a screen that gives no sign there is
     anything below it.
     Capping the height and letting the BODY scroll instead pins the footer —
     dots, disclosure, button — where it can always be reached. */
  #screen-onboard{justify-content:flex-end;min-height:calc(100vh - 90px);max-height:calc(100vh - 90px)}
  /* 44px touch minimum, applied to the four control groups measured below it
     at 390x844 and 430x932. None of these was unusable, but each was under the
     size the rest of the app already holds to, and the legal links were half
     of it. */
  .ob-skip{align-self:flex-end;color:var(--ink-2);font-size:14px;font-weight:700;
           padding:8px 12px;min-height:44px;display:inline-flex;align-items:center}
  html[lang="ar"] .ob-skip{font-size:15px;font-weight:400}
  /* min-height:0 so this column may shrink below its content: without it a
     flex item refuses to go under min-content and pushes the footer — the
     dots, the disclosure and the button that advances the tour — off the
     bottom of the viewport. That was reachable only by scrolling, on the one
     screen where the reader has no reason to think there is anything to
     scroll to. */
  .ob-body{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:10px 8px}
  /* The illustration is the one part of a tour card that can lose height
     without losing meaning, so it is what yields on a short screen. */
  .ob-art{width:190px;height:190px;flex:0 1 auto;min-height:0;margin-bottom:28px;position:relative;display:flex;align-items:center;justify-content:center}
  .ob-art svg{max-width:100%;max-height:100%}
  .ob-art::before{content:"";position:absolute;inset:-14%;border-radius:50%;
      background:radial-gradient(circle at 50% 45%, var(--teal-soft) 0%, transparent 68%);opacity:.75}
  .ob-art svg{position:relative}
  .ob-title{font-size:24px;color:var(--teal-ink);line-height:1.5;max-width:320px}
  .ob-sub{font-size:15px;color:var(--ink-2);margin-top:10px;max-width:320px}
  /* The one onboarding card that asks something. Choices are full-width and
     tall enough to be an obvious decision rather than a settings row. */
  .ob-pick{display:flex;flex-direction:column;gap:10px;margin-top:20px;width:100%;max-width:340px}
  .ob-pick[hidden]{display:none}
  .ob-choice{display:flex;flex-direction:column;align-items:flex-start;gap:4px;
    text-align:start;padding:14px 16px;min-height:44px;border-radius:var(--r-lg);
    background:var(--card);border:1.5px solid var(--line);
    transition:border-color var(--t-fast) var(--ease-out),background var(--t-fast) var(--ease-out),
      transform var(--t-fast) var(--ease-out)}
  .ob-choice b{font-size:16.5px;color:var(--ink)}
  .ob-choice span{font-size:13px;color:var(--ink-2);line-height:1.6}
  .ob-choice:active{transform:scale(.985)}
  .ob-choice.on{border-color:var(--teal);background:var(--teal-soft)}
  .ob-choice.on b{color:var(--teal-ink)}
  #obNext:disabled{opacity:.45;pointer-events:none}
  .ob-note{font-size:13px;line-height:1.6;color:var(--ink-2);text-align:center;
           margin:0 2px 12px}
  html[lang="ar"] .ob-note{font-size:14px}
  .ob-note[hidden]{display:none}
  .dots{display:flex;justify-content:center;gap:8px;margin:18px 0 16px}
  /* A display value beats the hidden attribute, so both need an explicit
     guard — this has bitten this file before. */
  .dots[hidden]{display:none}
  #obNext[hidden]{display:none}
  .dots button{width:8px;height:8px;border-radius:99px;background:var(--line);padding:0;transition:all .25s;
    box-sizing:content-box;border:18px solid transparent;background-clip:padding-box;margin:-18px}
  /* background-color, not the shorthand — the shorthand would reset the
     background-clip that keeps the 44px touch border invisible. */
  .dots button.on{width:22px;background-color:var(--teal)}

  /* loading */
  #screen-loading{align-items:center;justify-content:center;text-align:center}
  .lens-anim{width:84px;height:84px;margin-bottom:22px;animation:sway 1.6s ease-in-out infinite}
  @keyframes sway{0%,100%{transform:translateX(-9px) rotate(-4deg)}50%{transform:translateX(9px) rotate(4deg)}}
  .load-step{font-size:19px;color:var(--teal-ink);min-height:1.8em}
  .load-track{width:150px;height:2px;border-radius:2px;background:var(--line);margin:16px auto 0;overflow:hidden}
  .load-track span{display:block;height:100%;width:0;border-radius:2px;background:var(--teal);
      transition:width .62s cubic-bezier(.4,0,.2,1)}
  .load-sub{font-size:13px;color:var(--ink-2);margin-top:12px}

  /* result */
  .back[hidden]{display:none}
  .back{display:flex;align-items:center;gap:6px;color:var(--teal);font-size:14px;font-weight:700;padding:10px 2px;min-height:44px;align-self:flex-start}
  /* THE MIRROR BELONGS TO RTL, NOT LTR, AND IT HAD THEM THE WRONG WAY ROUND.
     The glyph is a left-pointing ‹. In English, back sits at the left edge and
     must point left — so it needs NO transform, and it was being flipped to
     point right, away from where it goes. In Arabic, back sits at the right
     edge and must point right, which is the flip — and it was getting none.
     Every .back control in the app, on both languages and every screen, was
     an arrow pointing forward on a button that goes back. */
  html[dir="rtl"] .back .bk{transform:scaleX(-1)}
  .score-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-2xl);padding:26px 20px 20px;text-align:center;box-shadow:var(--e2),var(--edge);--band:var(--teal)}
  /* THE MASTHEAD, on the .letterhead pattern the letter and the case file
     already use: mark, name in letterspaced caps, hairline rule beneath. Those
     are artifacts a reader sends onward, and this one is read the same way —
     it is the screen people screenshot and forward. The date sits at the far
     end rather than centred, so the row reads as a document header and not as
     a title. 10.5px carries letter-spacing, which is both the reason it is
     legible at that size and what test/type-scale.test.js requires of anything
     below 12px. */
  .rp-head{display:flex;align-items:center;gap:8px;padding-bottom:13px;margin-bottom:18px;
      border-bottom:1px solid var(--line);text-align:start}
  .rp-head .rp-mk{width:17px;height:17px;flex:none}
  .rp-kicker{font-family:var(--en);font-size:10.5px;font-weight:800;letter-spacing:.2em;
      text-transform:uppercase;color:var(--teal)}
  html[lang="ar"] .rp-kicker{font-family:var(--ar);font-weight:400;font-size:13px;
      letter-spacing:0;text-transform:none}
  .rp-date{margin-inline-start:auto;font-size:12px;color:var(--ink-2);
      font-variant-numeric:tabular-nums}
  /* The score is the emotional centre of the app, so it carries the verdict's
     colour rather than a constant brand teal. */
  .score-card[data-band="great"]{--band:var(--green)}
  .score-card[data-band="good"]{--band:var(--teal)}
  .score-card[data-band="fair"]{--band:var(--amber)}
  .score-card[data-band="poor"]{--band:var(--red)}
  /* The decision wins. A score band and a decision state can legitimately
     disagree — 68/100 is "good" on the score scale but still needs
     negotiating — and when they do, two colours arguing on one card is worse
     than either. Set after the band rules so it always takes precedence. */
  .score-card[data-decision="safe"]{--band:var(--green)}
  .score-card[data-decision="negotiate"]{--band:var(--amber)}
  .score-card[data-decision="lawyer"]{--band:var(--red)}
  /* THE RING SUPPORTS THE SENTENCE, it does not compete with it.
     It used to sit between the decision badge and the verdict sentence at
     120px with a 36px number — three elements saying the same thing in one
     viewport, none of them clearly first, and the largest of them was the
     abstraction rather than the answer. A reader does not act on 59; they act
     on "fair overall, but negotiate two clauses". So the sentence follows the
     badge directly, and the score follows the sentence at a size that reads
     as evidence for it. */
  .ring{width:92px;height:92px;margin:14px auto 10px;position:relative}
  .ring svg{width:100%;height:100%;transform:rotate(-90deg);overflow:visible}
  .ring circle.track{stroke:var(--line)}
  .ring circle.bezel{stroke:var(--line);opacity:.55}
  /* the arc carries a whisper of its own colour as light, never a gradient sweep */
  .ring circle.val{transition:stroke-dashoffset 1.15s cubic-bezier(.32,.72,.28,1);
      filter:drop-shadow(0 0 6px color-mix(in srgb, var(--band) 30%, transparent))}
  @supports not (color: color-mix(in srgb, red, blue)){ .ring circle.val{filter:none} }
  .ring .num{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
  .ring .num b{font-family:var(--en);font-size:24px;font-weight:800;letter-spacing:-.03em;
      color:var(--band);line-height:1;font-variant-numeric:tabular-nums}
  .ring .num i{font-style:normal;font-size:10.5px;color:var(--ink-2);direction:ltr;margin-top:3px;
      font-family:var(--en);letter-spacing:.06em}
  /* The decision reads first. It carries its own state colour rather than
     the score band, so a mostly-fine score with one serious clause still
     shows as needing attention. */
  .decision{--dc:var(--teal);--dc-bg:var(--teal-soft);--dc-ink:var(--teal-ink);
    display:flex;flex-direction:column;align-items:center;gap:6px;
    margin:0 0 20px;padding:16px 14px;border-radius:var(--r-lg);
    background:var(--dc-bg);border:1px solid color-mix(in srgb, var(--dc) 26%, transparent)}
  .decision[data-state="safe"]{--dc:var(--green);--dc-bg:var(--green-bg);--dc-ink:var(--green-ink)}
  .decision[data-state="negotiate"]{--dc:var(--amber);--dc-bg:var(--amber-bg);--dc-ink:var(--amber-ink)}
  .decision[data-state="lawyer"]{--dc:var(--red);--dc-bg:var(--red-bg);--dc-ink:var(--red-ink)}
  .decision .dc-ic{display:flex;color:var(--dc-ink)}
  .decision .dc-ic svg{width:26px;height:26px}
  .dc-label{font-size:19px;line-height:1.35;color:var(--dc-ink);text-wrap:balance}
  .dc-why{font-size:14px;color:var(--ink-2);line-height:1.6}
  .dc-conf{font-size:12px;color:var(--ink-2);line-height:1.55;text-wrap:balance}
  /* WHEN WE READ MOST OF IT, THIS IS FOOTNOTE. WHEN WE DID NOT, IT IS THE
     MOST IMPORTANT LINE ON THE CARD.
     The text was always correct — "we only recognised 3" — but it was set in
     the smallest, faintest type on a card headlined by a large confident
     number, which is the visual equivalent of saying it under your breath. A
     reader scanning a 92 has no reason to look for the caveat, so at low
     coverage the caveat stops being fine print. */
  .dc-conf[data-level="low"]{font-size:13px;opacity:1;color:var(--amber-ink);
    display:flex;gap:6px;align-items:flex-start;
    background:var(--amber-bg);border-radius:10px;padding:8px 10px;margin-top:4px}
  .dc-conf[data-level="low"] svg{width:15px;height:15px;flex:none;margin-top:1px}
  /* The rise moved to the motion block below and is scoped to .active there,
     so it replays on every arrival instead of once per page load. The
     no-preference wrapper went with it: the global reduced-motion reset now
     zeroes both duration AND delay, so a second opt-out here would only be a
     second place to keep in step. */
  .verdict{font-size:19px;color:var(--ink);line-height:1.7;text-wrap:balance;margin-top:14px}
  .doc-label{display:inline-block;margin-top:12px;font-size:13px;color:var(--teal);background:var(--teal-soft);border-radius:999px;padding:4px 14px;font-weight:700}
  /* 44px hit area via a transparent border, visual size unchanged */
  .how-built{display:block;margin:0 auto;font-size:12px;color:var(--ink-2);
      border:12px solid transparent;border-bottom-width:13px;background-clip:padding-box;
      box-shadow:inset 0 -1px 0 var(--line)}
  .how-built:hover{color:var(--teal)}
  /* THE COLOPHON. Four grey captions that used to sit loose under the ring,
     each centred on its own line, now one labelled block with a rule above it.
     Start-aligned rather than centred: centred text reads as a caption and
     invites a skim, and this is the block that answers "what was this read
     against" — the one a sceptical reader stops on. The .score-card is
     text-align:center, hence the explicit start here.

     .how-built keeps its 12px transparent border. That is not spacing — it is
     what carries the link past the 44px touch minimum that
     test/layout.test.js sweeps at 390 and 430px, and shrinking it to tidy the
     block would fail that sweep rather than look tidier.

     THE LEGEND USED TO LIVE HERE and is gone. It explained the three severity
     colours from inside .dk-a while the flags it explained were in .dk-b — on
     a laptop that is the other column. Its job moved into the tally above the
     findings, where the counts and the colour names are the same object, and
     its copy keys moved with it rather than being orphaned. */
  .rp-meta{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);text-align:start}
  .rp-meta-h{font-size:12px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
      color:var(--teal);margin:0 0 9px}
  html[lang="ar"] .rp-meta-h{font-weight:400;font-size:13px;letter-spacing:0;text-transform:none}
  .rp-meta .src-line{margin-top:0;padding-top:0;border-top:0;text-align:start}
  .rp-meta .src-line + .src-line,.rp-meta .currency{margin-top:8px}
  .rp-meta .currency{text-align:start}
  .rp-meta .how-built{margin:2px 0 0;margin-inline-start:-12px}
  /* THE FINDINGS HEADER. 16.5px matches .duties h3 — the two lists on this
     screen are peers ("what can they do to me" and "what did I agree to") and
     a heading a step apart would rank one over the other by accident.
     The tally wraps under the heading on a narrow phone rather than squeezing
     the title, and each chip carries its severity's own ink on its own tint,
     the pairs contrast.test.js already holds at 4.5:1. */
  .fx-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-top:18px}
  .fx-head h3{font-size:16.5px;color:var(--teal-ink);margin:0}
  .fx-tally{display:flex;gap:6px;flex-wrap:wrap;margin-inline-start:auto}
  .fx-tally[hidden]{display:none}
  .fx-chip{font-size:12px;line-height:1.6;border-radius:999px;padding:2px 10px;
      white-space:nowrap;font-weight:600}
  html[lang="ar"] .fx-chip{font-weight:400;font-size:13px}
  .fx-chip b{font-weight:800;font-variant-numeric:tabular-nums;margin-inline-end:2px}
  html[lang="ar"] .fx-chip b{font-weight:700}
  .fx-chip.red{background:var(--red-bg);color:var(--red-ink)}
  .fx-chip.amber{background:var(--amber-bg);color:var(--amber-ink)}
  .fx-chip.green{background:var(--green-bg);color:var(--green-ink)}
  .flags{margin-top:16px;display:grid;gap:10px}
  /* One scannable line per clause; detail is one tap away (and always in full
     on the clause-by-clause screen), so the result reads at a glance. */
  .flag{border-radius:var(--r-lg);padding:0;text-align:start;overflow:hidden}
  .flag>button{display:flex;gap:12px;align-items:center;width:100%;padding:13px 15px;text-align:start}
  .flag .dot{flex:none;width:26px;height:26px;border-radius:999px;display:flex;align-items:center;justify-content:center}
  .flag .dot svg{width:13px;height:13px}
  .flag .ttl{flex:1;min-width:0}
  .flag h4{font-size:15px;color:var(--ink);line-height:1.45}

  /* SEVERITY IS THE INFORMATION, SO SEVERITY GETS THE SIZE.
   *
   * Every flag was the identical row — 13px padding, a 15px title, a 26px dot
   * — whether it said "pause before signing" or "you're fine". On the one
   * screen whose entire job is to rank what matters, ranking was carried by
   * hue alone, and hue is the channel roughly one man in twelve reads badly
   * and nobody reads well in sunlight. The severity word added under each
   * title fixed the naming; it did not fix the WEIGHT, which is what a reader
   * scanning rather than reading actually uses.
   *
   * Three steps, all from the existing type scale: red gets 16.5px and a
   * larger dot, amber stays the 15px midpoint, green drops to 14px and tucks
   * in. The difference is deliberately legible at a glance and small enough
   * that a list of eight does not look like eight different components.
   *
   * NOT applied to the doors on home. Those are equal by a measured decision
   * — they drew 199px on a laptop against 354px on a phone until two equal
   * columns fixed it — and equal is correct there, because a situation is not
   * more or less severe than another situation. */
  .flag.red>button{padding:16px 15px}
  .flag.red h4{font-size:16.5px;line-height:1.4}
  .flag.red .dot{width:30px;height:30px}
  .flag.red .dot svg{width:15px;height:15px}
  .flag.green>button{padding:11px 15px}
  .flag.green h4{font-size:14px}
  .flag.green .dot{width:23px;height:23px}
  .flag.green .dot svg{width:12px;height:12px}
  /* ONE LADDER FOR BOTH LANGUAGES — 14 / 15 / 16.5. The first version bumped
     Arabic a step on the theory that Arabic reads smaller at the same size,
     and it put green at 15px, which is what amber already is: the Arabic
     ladder collapsed to two steps and only the measurement showed it. The
     padding and the dot carry weight of their own, so the same three sizes
     give a legible three-step ladder in both directions without a second set
     of rules to keep in step. */
  .flag .chev{flex:none;color:var(--ink-2);display:flex;transition:transform .2s ease}
  .flag .chev svg{width:15px;height:15px}
  html[dir="rtl"] .flag .chev{transform:scaleX(-1)}
  .flag.open .chev{transform:rotate(90deg)}
  html[dir="rtl"] .flag.open .chev{transform:scaleX(-1) rotate(90deg)}
  .flag .advice{max-height:0;overflow:hidden;transition:max-height .28s ease}
  .flag .advice>*{margin:0 15px 12px;margin-inline-start:53px}
  .flag .advice p{font-size:13px;color:var(--ink-2);line-height:1.7}
  .advice .tip{background:var(--card);border-radius:12px;padding:10px 13px;font-size:13px;color:var(--ink);line-height:1.7}
  .advice .tip b{color:var(--teal-ink)}
  /* The clause the reader's dispute is actually about. Marked as well as moved:
     position alone is not a statement, and this is one. */
  .flag.indispute{box-shadow:0 0 0 2px var(--teal)}
  .flag.indispute .fl-mark{display:flex}
  .fl-mark{display:none;align-items:center;gap:6px;font-size:12px;font-weight:700;
      color:var(--teal-ink);background:var(--teal-soft);padding:5px 12px}
  html[lang="ar"] .fl-mark{font-weight:400;font-size:13px}
  /* WHAT YOU AGREED TO DO. The whole result screen answers "what can they do
     to me"; nothing answered "what did I take on". A reader who only ever
     sees their rights walks into the obligation they did not read. */
  .duties{margin-top:18px}
  .duties h3{font-size:16.5px;color:var(--teal-ink);margin:0 0 4px}
  .duties .d-sub{font-size:13px;color:var(--ink-2);margin:0 0 12px;line-height:1.7}
  .duties ul{list-style:none;margin:0;padding:0;display:grid;gap:10px}
  .duties li{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
      padding:13px 15px;box-shadow:var(--e1),var(--edge)}
  .duties b{display:block;font-size:14px;color:var(--ink);margin-bottom:3px}
  .duties span{display:block;font-size:13px;color:var(--ink-2);line-height:1.7}
  .flag.red{background:var(--red-bg)} .flag.red .dot{background:var(--red)}
  .flag.amber{background:var(--amber-bg)} .flag.amber .dot{background:var(--amber)}
  .flag.green{background:var(--green-bg)} .flag.green .dot{background:var(--green)}

  /* negotiation letter upsell + paywall */
  .letter-tease{display:flex;align-items:center;gap:12px;width:100%;background:var(--amber-bg);border:1px solid var(--amber);border-radius:var(--r-lg);padding:14px 16px;margin-top:14px;text-align:start;box-shadow:var(--shadow)}
  .letter-tease .lock{flex:none;width:38px;height:38px;border-radius:12px;background:var(--amber);display:flex;align-items:center;justify-content:center}
  .letter-tease .lock svg{width:19px;height:19px}
  .letter-tease b{display:block;font-size:15px;color:var(--ink)}
  .letter-tease span{font-size:13px;color:var(--ink-2)}
  .letter-tease .go{margin-inline-start:auto;color:var(--amber);display:flex}

  /* Reads as a label, not as a second heading — the clause name stays the
     thing you scan for. Colour matches the row so it reinforces the tint
     rather than repeating it in a different key. */
  .flag .sev-label{
    display:block;font-size:12px;line-height:1.3;margin-top:2px;font-weight:600;
    color:var(--ink-2);
  }
  .flag.red .sev-label{color:var(--red)}
  .flag.amber .sev-label{color:var(--amber)}
  .flag.green .sev-label{color:var(--green)}

  /* Suggestion and track chips inside an assistant message. Sized to the 44px
     touch minimum the rest of the app holds to, and wrapping rather than
     scrolling sideways — long Arabic labels must never clip. */
  /* Tertiary. No card, no border, no price — nothing that reads as an option
     in the list above it. */
  .pw-biz{
    display:block;width:100%;background:none;border:0;cursor:pointer;
    font:inherit;font-size:13px;color:var(--ink-2);text-align:center;
    padding:14px 8px;min-height:44px;text-decoration:underline;
    text-underline-offset:3px;
  }
  .pw-biz:focus-visible{outline:2px solid var(--teal);outline-offset:2px;border-radius:8px}

  .as-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
  .as-chip{
    font:inherit;font-size:14px;line-height:1.35;min-height:44px;
    padding:10px 14px;border-radius:var(--r-lg);cursor:pointer;
    background:var(--card);color:var(--teal-deep);
    border:1px solid var(--teal);text-align:start;
  }
  .as-chip:active{transform:scale(.97)}
  .as-chip:focus-visible{outline:2px solid var(--teal);outline-offset:2px}

  .pw-note{text-align:center;font-size:13px;color:var(--green);font-weight:700;margin:2px 0 12px}
  html[lang="ar"] .pw-note{font-weight:400;font-size:14px}
  .preview{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);padding:22px;overflow:hidden;box-shadow:var(--e2),var(--edge)}
  .preview .ltr-head{font-size:13px;color:var(--ink-2);margin-bottom:10px}
  /* pre-line, like .letter .body below. Without it the preview — the one
     screen whose job is to make the document look worth buying — collapsed
     every line break and rendered as one run-on paragraph. */
  .preview .body{font-size:14px;line-height:1.9;color:var(--ink);white-space:pre-line}
  /* What the assessment contains, shown before payment: counts and names, no
     computed figure. Real withheld value described honestly. */
  .pw-shape{margin-top:14px;padding-top:14px;border-top:1px dashed var(--line)}
  .pw-shape h4{font-size:13px;font-weight:700;color:var(--ink-2);margin-bottom:9px}
  .pw-shape ul{list-style:none;display:flex;flex-direction:column;gap:7px}
  .pw-shape li{display:flex;align-items:flex-start;gap:9px;font-size:14px;color:var(--ink);line-height:1.65}
  .pw-shape li>span:first-child{flex:none;width:18px;height:18px;margin-top:2px;border-radius:999px;
      background:var(--teal-soft);color:var(--teal-ink);font-size:12px;font-weight:800;
      display:flex;align-items:center;justify-content:center;font-family:var(--en)}
  .pw-shape li.dim{color:var(--ink-2)}
  .pw-shape li.dim>span:first-child{background:var(--sand);color:var(--ink-2)}
  .locked-row{display:flex;align-items:center;gap:11px;margin-top:16px;padding-top:15px;
      border-top:1px dashed var(--line);color:var(--ink-2);font-size:14px}
  .locked-row .lk{flex:none;width:32px;height:32px;border-radius:999px;background:var(--teal);
      display:flex;align-items:center;justify-content:center}
  .locked-row .lk svg{width:16px;height:16px}
  .guarantee{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:14px;
      font-size:13px;color:var(--green)}
  .guarantee svg{flex:none;width:16px;height:16px}
  .plans{display:grid;gap:10px;margin-top:14px}
  .plan{display:flex;align-items:center;gap:12px;background:var(--card);border:2px solid var(--line);border-radius:var(--r-lg);padding:13px 15px;text-align:start;transition:border-color .15s}
  .plan.sel{border-color:var(--teal);background:var(--teal-soft)}
  /* THE RECOMMENDATION IS AN OPINION WE ARE WILLING TO STATE, so it is stated
     at a size someone can see. It was a 12px amber badge on a card identical
     to the two beside it, which is the visual weight of a footnote for the
     one line on the screen that is actually advice.
     Size and border, not colour: .sel already owns the teal treatment, and
     two things competing for "this one" would be worse than none. A reader
     who wants a different plan still sees three plans. */
  .plan.rec{padding:17px 15px;border-width:2px;border-color:var(--teal-ink)}
  .plan.rec b{font-size:16.5px}
  html[lang="ar"] .plan.rec b{font-size:19px}
  .plan.rec .price{font-size:19px}
  /* Selected wins the border back — the reader's own choice outranks ours. */
  .plan.rec.sel{border-color:var(--teal)}
  .plan .radio{flex:none;width:20px;height:20px;border-radius:99px;border:2px solid var(--line);display:flex;align-items:center;justify-content:center}
  .plan.sel .radio{border-color:var(--teal)}
  .plan.sel .radio::after{content:"";width:10px;height:10px;border-radius:99px;background:var(--teal)}
  .plan b{display:block;font-size:15px;color:var(--ink)}
  .plan span{font-size:12px;color:var(--ink-2);line-height:1.5;display:block}
  .plan .price{margin-inline-start:auto;font-family:var(--en);font-weight:800;font-size:16.5px;color:var(--teal-ink);white-space:nowrap}
  .plan .badge{display:inline-block;font-size:12px;font-weight:700;color:var(--amber-ink);background:var(--amber-bg);border-radius:99px;padding:1px 8px;margin-inline-start:6px;vertical-align:middle}
  .pay-methods{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:14px;
      font-size:12px;color:var(--ink-2);flex-wrap:wrap}
  .pay-methods svg{width:14px;height:14px;color:var(--teal)}
  .pay-methods i{font-style:normal;background:var(--card);border:1px solid var(--line);border-radius:8px;padding:2px 10px;font-family:var(--en);font-weight:700}
  .au-none{font-size:14px;color:var(--ink-2);line-height:1.7;background:var(--card);
      border:1px solid var(--line);border-radius:var(--r-md);padding:14px 16px;margin:4px 0 0}
  .au-none[hidden]{display:none}
  .acc-who{font-weight:600;margin:2px 0 12px;word-break:break-all}
  .legal-links{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:12px}
  .legal-id{font-size:12px;line-height:1.6;color:var(--ink-2);margin-top:10px}
  .legal-links a{font-size:13px;color:var(--teal-ink);text-decoration:underline;
    text-underline-offset:2px;min-height:44px;display:inline-flex;align-items:center}
  .demo-tag{text-align:center;font-size:12px;color:var(--ink-2);margin-top:8px}
  .acc-anchor{text-align:center;font-size:12px;color:var(--ink);background:var(--teal-soft);
      border-radius:var(--r-sm);padding:9px 12px;margin-top:12px;line-height:1.6}

  /* unlocked letter */
  /* The letter is the artifact the user actually sends, so it is presented as
     stationery: letterhead, hairline rules, generous margins. The letterhead
     lives outside #letterBody so copying still yields clean text. */
  .letter{background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);padding:26px 24px 22px;box-shadow:var(--e2),var(--edge)}
  .letterhead{display:flex;align-items:center;justify-content:center;gap:8px;padding-bottom:16px;
      margin-bottom:20px;border-bottom:1px solid var(--line)}
  .letterhead svg{width:18px;height:18px}
  .letterhead span{font-family:var(--en);font-size:10.5px;font-weight:800;letter-spacing:.24em;
      text-transform:uppercase;color:var(--teal)}
  .letter .body{font-size:15px;line-height:2.05;color:var(--ink);white-space:pre-line}
  .ltr-send{margin-top:14px}
  .ltr-send b{display:block;font-size:15px;color:var(--teal-ink);margin-bottom:8px}
  .ltr-send ul{list-style:none;margin:0;padding:0;display:grid;gap:9px}
  .ltr-send li{font-size:13px;line-height:1.7;color:var(--ink-2);padding-inline-start:16px;position:relative}
  .ltr-send li::before{content:"";position:absolute;inset-inline-start:0;top:8px;
      width:6px;height:6px;border-radius:99px;background:var(--teal)}
  .letterfoot{margin-top:20px;padding-top:14px;border-top:1px solid var(--line);
      font-size:12px;color:var(--ink-2);text-align:center}
  .letter-actions{display:flex;gap:10px;margin-top:14px}
  .letter-actions .primary{margin-top:0;flex:1}
  .ghost{flex:1;border:2px solid var(--teal);color:var(--teal);border-radius:var(--r-lg);padding:13px;font-weight:700;font-size:15px}

  /* greeting + notices */
  .greet{font-size:14px;color:var(--teal);font-weight:700;margin:16px 2px -2px}
  html[lang="ar"] .greet{font-weight:400;font-size:16.5px}
  .notice[hidden]{display:none}
  .notice{background:var(--amber-bg);border:1px solid var(--amber);border-radius:var(--r-md);
          padding:11px 14px;margin-top:12px;font-size:14px;color:var(--ink)}

  /* all-clear celebration — the reward for a contract that needed no fight */
  .all-clear[hidden]{display:none}
  .all-clear{background:var(--green-bg);border-radius:var(--r-xl);padding:20px 18px;margin-top:16px;text-align:center}
  .all-clear .ac-tick{width:46px;height:46px;border-radius:999px;background:var(--green);
       display:flex;align-items:center;justify-content:center;margin:0 auto 12px;
       animation:pop var(--t-slow) var(--ease-spring) both}
  .all-clear .ac-tick svg{width:24px;height:24px}
  .all-clear b{display:block;font-size:19px;color:var(--ink)}
  .all-clear span{display:block;font-size:14px;color:var(--ink-2);margin-top:5px;line-height:1.7}
  @keyframes pop{from{transform:scale(.4);opacity:0}to{transform:scale(1);opacity:1}}

  /* could-not-read state — no score, by design */
  #screen-noread{justify-content:center;text-align:center}
  .nr-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px 6px}
  .nr-mark{width:64px;height:64px;opacity:.5;margin-bottom:18px}
  #screen-noread h2{font-size:24px;color:var(--teal-ink);line-height:1.5}
  #screen-noread p{font-size:15px;color:var(--ink-2);margin-top:8px;max-width:320px}
  .nr-tips{list-style:none;margin-top:20px;display:grid;gap:8px;text-align:start;width:100%;max-width:330px}
  .nr-tips li{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
              padding:11px 14px;font-size:14px;color:var(--ink);display:flex;gap:9px;align-items:flex-start;box-shadow:var(--e1),var(--edge)}
  .nr-tips li::before{content:"";flex:none;width:6px;height:6px;border-radius:99px;background:var(--teal);margin-top:9px}
  .ghost.wide{width:100%;margin-top:10px;flex:none}

  /* motion: screens enter along the reading direction */
  .screen.active{animation:screen-in var(--t-slow) var(--ease-out) both}
  @keyframes screen-in{from{opacity:0;transform:translateX(calc(var(--dir,1) * 16px)) scale(.985)}
                       to{opacity:1;transform:none}}
  .screen.active.back{animation-name:screen-back}
  @keyframes screen-back{from{opacity:0;transform:translateX(calc(var(--dir,1) * -16px)) scale(.985)}
                         to{opacity:1;transform:none}}
  /* Tabs are siblings, not parents — no lateral push, just a settle. */
  .screen.active.lateral{animation-name:screen-lateral}
  @keyframes screen-lateral{from{opacity:0;transform:scale(1.012)}to{opacity:1;transform:none}}
  /* Committed by a gesture: the reader supplied the motion, so the destination
     only needs to appear. A directional slide here would play a movement that
     has already happened, in the opposite direction to the thumb. */
  .screen.active.gesture{animation-name:screen-gesture;animation-duration:var(--t-fast)}
  @keyframes screen-gesture{from{opacity:0}to{opacity:1}}
  /* Live drag: the screen tracks the finger, transitions suspended. */
  .screen.dragging{animation:none !important;transition:none !important;will-change:transform}
  .screen.settling{transition:transform var(--t) var(--ease-spring), opacity var(--t) var(--ease-out)}
  /* --g is the GROUP's base delay, --d the item's offset within it. Two
     variables rather than one because the item offset is set in JS, where the
     loop index lives, and the group offset belongs in CSS beside the layout it
     sequences. calc() adds them so neither has to know about the other. */
  .flag,.tl-item{animation:settle var(--t) var(--ease-out) both;
      animation-delay:calc(var(--g,0ms) + var(--d,0ms))}
  @keyframes settle{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

  /* THE RESULT SCREEN ARRIVES IN THE ORDER IT SHOULD BE READ.
   *
   * Everything on this screen used to appear at once except the flag cards,
   * which had a 40ms internal stagger starting at 0 — so they raced the
   * screen's own entry animation and the sequence read as one event with some
   * jitter in it. The verdict, the score and the four actions had nothing.
   *
   * The order below is the order the screen answers its own question: what is
   * the verdict, then what did we find, then what can you do about it. It is
   * the reading order in both directions — on desktop .dk-a and .dk-b are
   * side-by-side columns, and column 1 is the start side, which is the left in
   * English and the right in Arabic.
   *
   * SCOPED TO .active, WHICH IS ALSO A FIX. .decision carried `animation:rise`
   * unconditionally, so it played once on page load and never again — a reader
   * who analysed a second contract got no motion at all on the line that
   * matters most. A CSS animation starts when its selector begins to match, so
   * scoping to .active replays the whole sequence on every arrival.
   *
   * BUDGETED, NOT DECORATIVE. The last action lands at 440ms. During its delay
   * an element holds opacity:0 but keeps its box and stays clickable, so a
   * reader who knows where the button is can still hit it; nothing is disabled
   * and nothing moves under the thumb. Under prefers-reduced-motion every
   * delay above is zeroed and the screen is simply complete — see the note at
   * the top of this file, which had to be fixed before any of this was safe to
   * add. */
  #screen-result.active .decision{animation:rise var(--t) var(--ease-spring) both}
  #screen-result.active .verdict{animation:settle var(--t) var(--ease-out) both;
      animation-delay:60ms}
  #screen-result.active #flags{--g:120ms}
  /* The actions use --t-fast rather than --t. They are the tail of the
     sequence, so their duration is what decides when the screen is finally
     settled — and by the time they arrive the reader has already been given
     the verdict and the findings, so the arrival needs to be quick rather than
     considered. At --t the last one landed at 680ms; at --t-fast it lands at
     540ms, which is the same sequence without the drag at the end. */
  /* NAMED, NOT COUNTED. These four delays used to be addressed as
     .dk-b > button:nth-of-type(1..4). That is correct only for exactly the
     current markup: add a button anywhere in .dk-b — an upgrade prompt, a
     second CTA — and every delay silently shifts onto a different element,
     and so does the probe in test/motion.test.js that asserts this sequence.
     Nothing fails; the guard just quietly stops watching what it names. The
     ids already exist, so naming them costs nothing and takes the trap out. */
  #screen-result.active .duties:not([hidden]),
  #screen-result.active .dk-b > button{animation:settle var(--t-fast) var(--ease-out) both}
  #screen-result.active .duties:not([hidden]){animation-delay:290ms}
  #screen-result.active .dk-b > .detail{animation-delay:290ms}
  #screen-result.active #letterTease{animation-delay:320ms}
  #screen-result.active #trackTease{animation-delay:350ms}
  #screen-result.active #assistTease{animation-delay:380ms}
  .primary:active,.sample:active,.plan:active,.letter-tease:active,.track-tease:active,
  .ghost:active,.fb-btns button:active{transform:scale(.978)}
  .primary,.sample,.plan,.letter-tease,.track-tease,.ghost,.fb-btns button{transition:transform var(--t-fast) var(--ease-spring),box-shadow var(--t-fast) var(--ease-out)}

  /* letter builder — reading the contract is how the letter gets written */
  .add-btn{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--teal);
      color:var(--teal);background:none;border-radius:999px;padding:7px 13px;font-size:13px;
      font-weight:700;min-height:44px;transition:background .15s,color .15s,border-color .15s}
  html[lang="ar"] .add-btn{font-weight:400;font-size:14px}
  .add-btn svg{width:13px;height:13px}
  .add-btn.on{background:var(--teal);border-color:var(--teal);color:var(--on-teal)}
  .clause .add-btn{margin:2px 16px 14px}
  .advice .add-btn{margin-top:10px}

  .builder[hidden]{display:none}
  .builder{position:sticky;bottom:14px;z-index:5;display:flex;align-items:center;gap:12px;
      background:var(--teal);color:var(--on-teal);border-radius:var(--r-xl);padding:13px 15px;
      margin-top:14px;box-shadow:var(--e3);animation:rise var(--t-slow) var(--ease-spring) both}
  @keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
  .builder .bcount{flex:1;font-size:14px;font-weight:700}
  html[lang="ar"] .builder .bcount{font-weight:400;font-size:16.5px}
  .builder .bview{background:var(--on-teal);color:var(--teal);border-radius:12px;
      padding:9px 15px;font-size:14px;font-weight:700;white-space:nowrap}
  html[lang="ar"] .builder .bview{font-weight:400;font-size:15px}
  .builder.bump{animation:bump var(--t) var(--ease-spring)}
  @keyframes bump{0%{transform:none}35%{transform:scale(1.035)}100%{transform:none}}

  .letter-tease.building .lock{background:var(--teal)}
  .letter-tease.building{background:var(--teal-soft);border-color:var(--teal)}
  .letter-tease.building .go{color:var(--teal)}

  /* sources, currency, escalation */
  .stamp{display:flex;gap:11px;align-items:flex-start;background:var(--teal-soft);border-radius:var(--r-md);
      padding:13px 15px;margin:4px 0 14px}
  .stamp svg{flex:none;width:17px;height:17px;color:var(--teal);margin-top:2px}
  .stamp b{display:block;font-size:14px;color:var(--ink)}
  .stamp span span{font-size:13px;color:var(--ink-2);line-height:1.6}
  .src-list{display:grid;gap:9px;margin-top:6px}
  .src{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-md);padding:13px 15px;text-decoration:none;box-shadow:var(--e1),var(--edge);
      transition:border-color .15s}
  .src:hover{border-color:var(--teal)}
  .src .tx{flex:1;min-width:0}
  .src b{display:block;font-size:14px;color:var(--ink)}
  .src .tx>span{display:block;font-size:13px;color:var(--ink-2);line-height:1.55}
  .src .rev{font-size:12px;color:var(--teal);margin-top:4px}
  .src>svg{flex:none;width:15px;height:15px;color:var(--ink-2)}
  html[dir="rtl"] .src>svg{transform:scaleX(-1)}
  .caveat{font-size:12px;color:var(--ink-2);line-height:1.7;margin-top:12px}
  .currency{font-size:12px;color:var(--ink-2);text-align:center;margin-top:6px}
  .escalate[hidden]{display:none}
  .escalate{display:flex;gap:12px;align-items:flex-start;background:var(--amber-bg);
      border:1px solid var(--amber);border-radius:var(--r-xl);padding:16px 17px;margin-top:16px;
      box-shadow:var(--e1),var(--edge)}
  .escalate .ic{flex:none;width:36px;height:36px;border-radius:var(--r-sm);background:var(--amber);
      display:flex;align-items:center;justify-content:center}
  .escalate .ic svg{width:19px;height:19px}
  .escalate b{display:block;font-size:15px;color:var(--ink);margin-bottom:4px}
  .escalate p{font-size:13px;color:var(--ink-2);line-height:1.7}
  .esc-cta{margin-top:11px;background:var(--teal);color:var(--on-teal);border-radius:var(--r-sm);
      padding:9px 15px;font-size:14px;font-weight:700;min-height:44px}
  html[lang="ar"] .esc-cta{font-weight:400;font-size:15px}
  .src-line{font-size:12px;color:var(--ink-2);margin-top:8px;padding-top:8px;border-top:1px solid var(--line)}
  /* A citation and an opinion must not look alike. Law carries the teal mark
     of an official source; methodology is visibly quieter and unmarked. */
  .src-line.law{color:var(--teal-ink)}
  .src-line.law::before{content:"§";margin-inline-end:5px;font-weight:700}
  /* The article is a link to our own sourced page about it. Underlined rather
     than recoloured: .src-line.law is already teal-ink against the card, and a
     second colour inside one short line would read as two kinds of statement
     where there is one. The underline is offset so it does not collide with
     the descenders in «المادة». */
  /* The row is the tap target: 44px, which is what test/layout.test.js sweeps
     this screen for. .linked rather than :has(.art-link) so the rule needs no
     selector support the rest of this file does not already assume. */
  /* 44px on the ANCHOR, not on the row. box-sizing is border-box here, so a
     min-height on .src-line is eaten by its own 8px padding and 1px rule and
     the link came out at 35 — which the sweep reported to the pixel. The
     control is what gets measured, so the control is what carries the floor. */
  .src-line.law.linked{display:flex;align-items:stretch}
  /* THE § MOVES INSIDE THE LINK. As a child of a flex container the row's own
     ::before computes to display:block and takes a whole line to itself — the
     marker sat stranded above the citation it marks. Re-hung on the anchor, it
     is back on the line AND inside the tap target, which is where a marker for
     a link belongs anyway. */
  .src-line.law.linked::before{content:none}
  .src-line.law.linked .art-link::before{content:"§";margin-inline-end:5px;font-weight:700}
  /* 46, not 44. The anchor measured 43 at the floor of 44: a flex item's
     min-height loses to fractional layout often enough that sitting exactly on
     the limit makes the sweep a coin toss. Two pixels of headroom is cheaper
     than a guard that fails once a week. */
  .src-line.law.linked .art-link{display:flex;align-items:center;flex:1;min-width:0;min-height:46px}
  .src-line.law .art-link{color:inherit;text-decoration:underline;
      text-underline-offset:3px;text-decoration-thickness:1px;
      text-decoration-color:color-mix(in srgb, var(--teal-ink) 45%, transparent)}
  .src-line.law .art-link:hover,.src-line.law .art-link:focus-visible{
      text-decoration-color:var(--teal-ink)}
  @supports not (color: color-mix(in srgb, red, blue)){
    .src-line.law .art-link{text-decoration-color:var(--teal-ink)}
  }
  .src-line.method{font-style:italic}
  /* The scope line is not italic and not a footnote: it is the sentence that
     explains why the list above is as short as it is, and on a lease it is
     load-bearing. Amber-tinted rather than grey for the same reason the cap
     note on a clamped input is — the reader is being told a limit, not given
     a citation. */
  .src-line.scope{font-style:normal;color:var(--ink);background:var(--amber-bg);
      border:0;border-radius:var(--r-md);padding:10px 13px;margin-top:10px;
      font-size:13px;line-height:1.65;text-align:start}
  .src-line[hidden]{display:none}
  .score-src{border-top:0;padding-top:0;margin-top:10px;text-align:center}

  /* Rights library */
  .lib-ask{background:var(--teal-soft);border:1px solid color-mix(in srgb, var(--teal) 26%, transparent);
    border-radius:14px;padding:14px 16px;margin-bottom:16px}
  .lib-ask p{font-size:13px;color:var(--teal-ink);line-height:1.65;margin-bottom:10px}
  .lib-ask-b{display:flex;gap:8px}
  .lib-ask-b button{flex:1;min-height:44px;border-radius:var(--r-md);background:var(--card);
    border:1px solid var(--line);color:var(--ink);font-size:14px;font-weight:700}
  .lib-ask-b button:hover{border-color:var(--teal);color:var(--teal-ink)}
  .lib-h{font-size:19px;color:var(--ink);margin:30px 0 4px}
  .lib-sub{font-size:13px;color:var(--ink-2);line-height:1.6;margin-bottom:14px}
  /* THE LIFECYCLE WAS IN THE DATA AND NOWHERE ON THE SCREEN.
     Sixteen identical rows ran past four headings set in 12px at the palette's
     lightest weight — so the reader scrolling for "my salary is late" scanned
     sixteen rows rather than the five under "while you're employed". The
     grouping is the same; it is now visible: a heavier heading, a rule that
     starts the group, and real air between one stage of a working life and
     the next. */
  .lib-g{font-size:13px;font-weight:800;letter-spacing:.02em;color:var(--teal-ink);
    margin:28px 0 10px;padding-top:16px;border-top:1px solid var(--line);
    display:flex;align-items:center;gap:8px}
  .lib-g::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--teal);flex:none}
  .lib-g:first-of-type{border-top:0;padding-top:0;margin-top:18px}
  .lib-item{background:var(--card);border:1px solid var(--line);border-radius:14px;
    margin-bottom:8px;overflow:hidden}
  .lib-item summary{list-style:none;cursor:pointer;padding:14px 16px;min-height:44px;
    display:flex;align-items:center;gap:10px;font-size:15px;font-weight:700;color:var(--ink);
    transition:background var(--t-fast) var(--ease-out)}
  .lib-item summary::-webkit-details-marker{display:none}
  .lib-item summary::after{content:"";margin-inline-start:auto;width:8px;height:8px;flex:none;
    border-inline-end:2px solid var(--ink-2);border-block-end:2px solid var(--ink-2);
    transform:rotate(45deg);transition:transform var(--t-fast) var(--ease-out)}
  .lib-item[open] summary::after{transform:rotate(-135deg)}
  .lib-item summary:hover{background:var(--teal-soft)}
  .lib-a{padding:0 16px 14px}
  /* pre-line: library answers are written with blank lines between paragraphs
     (the Article 53 answer names an uncertainty in a second paragraph). The
     assistant's .msg already honours them; this sink was collapsing them into
     one run-on block. */
  .lib-a p{font-size:14px;color:var(--ink-2);line-height:1.75;white-space:pre-line}
  .lib-go{margin-top:12px;min-height:44px;padding:10px 18px;border-radius:var(--r-md);
    background:var(--teal);color:var(--on-teal);font-size:14px;font-weight:700;
    transition:transform var(--t-fast) var(--ease-out)}
  .lib-go:active{transform:scale(.97)}
  @media (prefers-reduced-motion:no-preference){
    .lib-item[open] .lib-a{animation:rise var(--t-fast) var(--ease-out) both}
  }
  #eosSrc{text-align:center}
  .cost-line{font-size:13px;color:var(--ink);background:var(--card);border-radius:var(--r-sm);
      padding:9px 12px;margin-top:9px;line-height:1.6}
  .clause .src-line{margin:0 16px 12px;padding-top:9px}

  /* ---- premium motion components (additive) ---- */

  /* Skeleton: shows the shape of what is coming, alongside the existing
     loading copy — never instead of it. */
  .skel{display:grid;gap:10px;width:100%;max-width:330px;margin:22px auto 0}
  .skel-ring{width:104px;height:104px;border-radius:999px;margin:0 auto 6px;
      border:8px solid var(--line);opacity:.65}
  .sk{border-radius:var(--r-sm);background:var(--line);opacity:.55;position:relative;overflow:hidden}
  .sk.l1{height:13px;width:78%;margin:0 auto} .sk.l2{height:13px;width:56%;margin:0 auto}
  .sk.row{height:44px;border-radius:var(--r-lg)}
  .sk::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
      background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--card) 70%,transparent),transparent);
      animation:shimmer 1.5s var(--ease-move) infinite}
  @keyframes shimmer{to{transform:translateX(100%)}}
  .skel.fading{animation:skel-out var(--t) var(--ease-out) forwards}
  @keyframes skel-out{to{opacity:0;transform:scale(.98)}}

  /* Sliding tab indicator */
  .tabbar{position:sticky}
  /* left:0 IS LOAD-BEARING, AND ITS ABSENCE WAS INVISIBLE IN ENGLISH.
     moveTabIndicator() positions this with translateX(on.offsetLeft), which is
     an offset from the LEFT edge — so the element must start there. With no
     inset its static position resolves at the end of the row, which in an RTL
     grid is the right edge, and the translate then pushed it further right:
     measured 318px away from the tab it marks on a 390px Arabic phone, under a
     different tab entirely. English was correct by luck, because there the end
     of the row and offset zero are the same place.
     The desktop block found this and set left:0 under .bar only, fixing the
     symptom one breakpoint up and leaving Arabic-on-a-phone — the primary
     reader on the primary platform — with no current-tab pill at all. */
  .tab-ind{position:absolute;left:0;top:6px;height:calc(100% - 12px - env(safe-area-inset-bottom));
      border-radius:var(--r-md);background:var(--teal-soft);z-index:-1;
      transition:transform var(--t) var(--ease-spring), width var(--t) var(--ease-spring);
      pointer-events:none}
  .tab{position:relative}

  /* Reveal on scroll — JS adds .rv, so content is visible without JS */
  .rv{opacity:0;transform:translateY(18px)}
  .rv.in{opacity:1;transform:none;transition:opacity var(--t-slow) var(--ease-out),transform var(--t-slow) var(--ease-out)}

  /* Header condenses as you scroll */
  .bar{transition:padding var(--t) var(--ease-move)}
  .bar.tight{padding-top:10px;padding-bottom:6px}
  .bar .brand svg,.bar .brand .name-ar{transition:transform var(--t) var(--ease-move)}
  .bar.tight .brand svg{transform:scale(.86)}
  .bar.tight .brand .name-ar{transform:scale(.92)}

  /* Parallax: decorative only, a few pixels */
  .score-card .ring{will-change:transform}

  /* Copy toast — additive; the button label swap still happens */
  /* CLEAR OF THE TAB BAR AND OF THE HOME INDICATOR. bottom:26px was measured
     against nothing: the tab bar is sticky at the bottom of every root screen
     at roughly 64px plus the safe-area inset, so a toast sat behind it — and
     on a phone with a home indicator it sat under that too. The tab bar is not
     always present, so this clears it rather than tracking it; 26px of gap
     above where it would be is the same rhythm the original was reaching for. */
  .toast{position:fixed;inset-inline:0;bottom:calc(90px + env(safe-area-inset-bottom));
      margin:0 auto;width:max-content;max-width:80%;
      background:var(--teal);color:var(--on-teal);border-radius:999px;padding:11px 20px;
      font-size:14px;box-shadow:var(--e3);z-index:40;display:flex;align-items:center;gap:9px;
      animation:toast-in var(--t-slow) var(--ease-spring) both}
  .toast svg{width:16px;height:16px}

  /* THE CONFIRM DIALOG. The only one in the app, for the only two actions that
     cannot be undone.
     A scrim that BLURS as well as tints, because the point is not decoration:
     it takes the page out of focus so the question is the only readable thing
     on screen, which is what a question you cannot take back deserves. The
     tint is the brand's own --page rather than black, so the app reads as
     having dimmed itself rather than as having something dropped on top of it.
     backdrop-filter is progressive — where it is unsupported the tint alone
     still separates the layers, so nothing depends on it. */
  .dlg::backdrop{background:color-mix(in srgb, var(--page) 62%, transparent);
      backdrop-filter:blur(6px) saturate(.85)}
  /* margin:auto explicitly. The UA centres a modal dialog through `margin:auto`
     against `inset:0`, and it only holds while both are the browser's own —
     setting any of the box properties here dropped it to the top edge, where
     it read as a notification bar rather than as a question. The inline
     padding is a floor, so the panel never touches the edge of a small
     screen. */
  .dlg{border:0;padding:0;background:none;color:var(--ink);
      inset:0;margin:auto;width:min(400px, calc(100vw - 36px));max-height:calc(100vh - 48px)}
  .dlg[open]{display:block}
  .dlg::backdrop{animation:dlg-fade var(--t-fast) var(--ease-out) both}
  .dlg[open]{animation:dlg-rise var(--t) var(--ease-spring) both}
  @keyframes dlg-fade{from{opacity:0}to{opacity:1}}
  @keyframes dlg-rise{from{opacity:0;transform:translateY(12px) scale(.97)}
                      to{opacity:1;transform:none}}
  /* The panel itself, inside the dialog box so the animation above can move it
     without fighting the centring the dialog element does. */
  .dlg h2,.dlg p,.dlg .dlg-acts{background:var(--card);margin:0;padding:0 22px}
  .dlg h2{font-size:19px;color:var(--ink);padding-top:22px;line-height:1.5;
      border-radius:var(--r-xl) var(--r-xl) 0 0}
  .dlg p{font-size:15px;color:var(--ink-2);line-height:1.75;padding-top:10px}
  .dlg-acts{display:flex;flex-direction:column;gap:9px;padding-top:18px;
      padding-bottom:20px;border-radius:0 0 var(--r-xl) var(--r-xl);
      box-shadow:var(--e3)}
  /* Stacked, not side by side: at 400px two buttons in a row give each about
     170px, and «امسح كل شيء من هذا الجهاز» does not fit in 170px without
     wrapping to two lines at a smaller size. A column also puts the safe
     answer where a thumb rests. */
  .dlg-acts button{width:100%;min-height:50px;font-size:15px}
  html[lang="ar"] .dlg-acts button{font-size:16.5px}
  /* Destructive, and coloured like it — but still a real button rather than a
     dimmed one: --on-teal on --red is the same pairing the red flag dot uses
     and clears AA. The safe answer is the ghost, which is the quieter of the
     two without being harder to read. */
  .dlg .primary.danger{background:var(--red);color:var(--on-teal);box-shadow:none}
  .dlg .ghost{border-color:var(--line);color:var(--ink)}
  .toast.out{animation:toast-out var(--t) var(--ease-out) forwards}
  @keyframes toast-in{from{opacity:0;transform:translateY(20px) scale(.94)}to{opacity:1;transform:none}}
  @keyframes toast-out{to{opacity:0;transform:translateY(12px) scale(.97)}}

  /* Draw-on confirmation ticks */
  .draw path{stroke-dasharray:24;stroke-dashoffset:24;animation:draw 260ms var(--ease-spring) forwards}
  @keyframes draw{to{stroke-dashoffset:0}}

  /* Press depth: scale paired with shadow, so it reads as physical */
  .sample:active,.assist-entry:active,.brow:active,.src:active,.doc:active{box-shadow:var(--e1)}
  .assist-entry,.brow,.src,.doc{transition:transform var(--t-fast) var(--ease-spring),
      box-shadow var(--t-fast) var(--ease-out),border-color var(--t-fast) var(--ease-out)}
  .assist-entry:active,.brow:active,.src:active,.doc:active{transform:scale(.985)}

  /* Segmented controls and radios settle with a spring */
  .seg button,.plan .radio,.opts button{transition:background var(--t-fast) var(--ease-out),
      color var(--t-fast) var(--ease-out),border-color var(--t-fast) var(--ease-out)}
  .plan .radio::after{animation:pop-dot var(--t-fast) var(--ease-spring) both}
  @keyframes pop-dot{from{transform:scale(0)}to{transform:scale(1)}}

  /* Expanded flag content fades in after the height settles */
  .flag.open .advice>*{animation:adv-in var(--t) var(--ease-out) both;animation-delay:90ms}
  @keyframes adv-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

  /* Reduced motion: neutralise everything decorative, keep everything usable */
  @media (prefers-reduced-motion: reduce){
    .sk::after,.skel,.toast,.draw path,.rv,.rv.in,.tab-ind,.flag.open .advice>*{
      animation:none !important;transition:none !important;transform:none !important;opacity:1 !important}
    .rv{opacity:1 !important;transform:none !important}
  }

  /* file intake */
  .intake{display:grid;grid-template-columns:1fr auto;gap:9px;margin-top:4px}
  .intake.over .up-main{border-color:var(--teal);background:var(--teal-soft)}
  .up-main{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-lg);padding:14px 15px;cursor:pointer;box-shadow:var(--e1),var(--edge);
      transition:border-color .15s,background .15s}
  .up-main:hover{border-color:var(--teal)}
  .up-main .ic{flex:none;width:38px;height:38px;border-radius:var(--r-sm);background:var(--teal);
      display:flex;align-items:center;justify-content:center;box-shadow:var(--e1)}
  .up-main .ic svg{width:19px;height:19px}
  .up-main b{display:block;font-size:15px;color:var(--ink)}
  .up-main span span{font-size:12px;color:var(--ink-2)}
  .up-main.busy{opacity:.6;pointer-events:none}
  .up-main.busy .ic{animation:pulse 1s ease-in-out infinite}
  @keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}
  .up-photo{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
      width:74px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
      color:var(--ink-2);font-size:12px;box-shadow:var(--e1),var(--edge);transition:color .15s,border-color .15s}
  .up-photo:hover{color:var(--teal);border-color:var(--teal)}
  .up-photo svg{width:21px;height:21px}
  /* Unavailable, drawn the same way .au-btn.soon is: a dashed edge and no
     fill, so it reads as "not yet" at a glance rather than looking live and
     then refusing. No opacity fade — the badge is the one word that has to be
     legible here. */
  .up-photo.soon{cursor:default;background:transparent;border-style:dashed;box-shadow:none}
  .up-photo.soon:hover{color:var(--ink-2);border-color:var(--line)}
  .up-photo .badge{font-size:12px;font-weight:700;color:var(--amber-ink);
      background:var(--amber-bg);border-radius:99px;padding:1px 7px;line-height:1.5}
  .intake + .or{margin:16px 0 10px}

  /* tab bar — permanent orientation across the four roots */
  .tabbar[hidden]{display:none}
  /* Columns come from however many tabs TABS holds, rather than a hardcoded
     count that a fifth tab would silently break. */
  .tabbar{position:sticky;bottom:0;z-index:6;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;
      background:color-mix(in srgb, var(--sand) 88%, transparent);backdrop-filter:blur(12px);
      border-top:1px solid var(--line);margin:18px -18px 0;padding:8px 10px calc(8px + env(safe-area-inset-bottom))}
  @supports not (backdrop-filter: blur(4px)){ .tabbar{background:var(--sand)} }
  .tab{display:flex;flex-direction:column;align-items:center;gap:4px;padding:7px 4px;border-radius:var(--r-md);
      color:var(--ink-2);transition:color .15s}
  .tab svg{width:21px;height:21px}
  /* Five columns on a 360px phone is ~70px each. The label must shrink to fit
     rather than wrap to two lines and shove the bar's height around. */
  .tab span{font-size:10.5px;font-weight:700;max-width:100%;overflow:hidden;
      text-overflow:ellipsis;white-space:nowrap}
  html[lang="ar"] .tab span{font-weight:400;font-size:12px}
  .tab.on{color:var(--teal)}
  .tab.on svg{stroke-width:2.3}

  /* future — the roadmap screen. Reuses the card surface, radius, line and
     amber badge the rest of the app already uses; nothing new is invented
     here, so the screen reads as the same product rather than a landing page
     that wandered in. Single column at every width: these are things to read,
     not options to compare, and a two-up grid on a phone makes eight-word
     descriptions into columns two words wide. */
  .fu-kicker{font-size:13px;font-weight:700;color:var(--teal);margin:0 2px 6px;
      letter-spacing:.02em}
  html[lang="ar"] .fu-kicker{font-weight:400;font-size:14px;letter-spacing:0}
  .fu-h{font-size:13px;font-weight:700;color:var(--ink-2);margin:22px 2px 10px;
      letter-spacing:.01em}
  html[lang="ar"] .fu-h{font-weight:400;font-size:15px}
  .fu-step{display:flex;gap:12px;align-items:flex-start;padding:11px 0}
  .fu-step + .fu-step{border-top:1px solid var(--line)}
  .fu-dot{flex:none;width:26px;height:26px;border-radius:50%;display:flex;align-items:center;
      justify-content:center;font-size:12px;font-weight:700;background:var(--sand);
      color:var(--ink-2);border:1px solid var(--line)}
  .fu-step.now .fu-dot{background:var(--teal);color:var(--on-teal);border-color:var(--teal)}
  .fu-step div:last-child,.fu-card div:last-child{display:flex;flex-direction:column;gap:3px}
  .fu-step b,.fu-card b,.fu-cat b{font-size:15px;color:var(--teal-ink)}
  .fu-step span,.fu-card span,.fu-cat span{font-size:13px;line-height:1.65;color:var(--ink-2)}
  .fu-card{display:flex;gap:12px;align-items:flex-start;background:var(--card);
      border:1px solid var(--line);border-radius:var(--r-md);padding:13px 14px;margin-bottom:9px}
  .fu-ic{flex:none;font-size:24px;line-height:1.2}
  .fu-cat{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
      padding:12px 14px;margin-bottom:9px}
  /* The name and its badge share a line; the description gets its own, or it
     runs straight on from the badge and reads as one sentence. */
  .fu-cat span{display:block;margin-top:5px}
  .fu-cat.now{border-color:color-mix(in srgb, var(--teal) 34%, var(--line))}
  /* The badge already exists for plans; scoped here so a "coming soon" chip
     looks like the "not yet available" chip a reader has already met. */
  .fu-card .badge,.fu-cat .badge,.fu-step .badge{display:inline-block;font-size:12px;
      font-weight:700;color:var(--amber-ink);background:var(--amber-bg);border-radius:99px;
      padding:1px 8px;margin-inline-start:6px;vertical-align:middle}
  .fu-card .badge,.fu-step .badge{align-self:flex-start;margin-inline-start:0}
  .fu-cat .badge.now,.fu-step .badge.now{color:var(--on-teal);background:var(--teal)}

  /* home: trust line, sample disclosure, saved contracts */
  /* min-height, because the tap target was depending on the LANGUAGE. This
     line wraps to two lines in English (~44px) and fits on one in Arabic
     (~25px), so the same control was comfortably tappable for one reader and
     under half the minimum for the other. Height should not be a translation
     side effect. */
  .privacy-line{display:flex;align-items:center;gap:8px;width:100%;text-align:start;
      margin-top:12px;padding:4px 2px;min-height:44px;
      color:var(--ink-2);font-size:12px;line-height:1.6}
  .privacy-line svg{flex:none;width:15px;height:15px;color:var(--teal)}
  .privacy-line span{flex:1;border-bottom:1px solid var(--line);padding-bottom:1px}
  .samples-toggle{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
      margin-top:20px;padding:11px;border:1px solid var(--line);border-radius:var(--r-md);
      color:var(--ink-2);font-size:14px;transition:color .15s,border-color .15s}
  .samples-toggle:hover{color:var(--teal);border-color:var(--teal)}
  .samples-toggle .chev{display:flex;transition:transform .2s}
  .samples-toggle .chev svg{width:14px;height:14px}
  .samples-toggle.open .chev{transform:rotate(180deg)}
  .samples[hidden]{display:none}
  .samples{margin-top:9px}
  .mc-list[hidden]{display:none}
  .mc-list{display:grid;gap:9px;margin-bottom:6px}
  .paste-hint.nudge{color:var(--red);animation:nudge .4s ease}
  @keyframes nudge{0%,100%{transform:none}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
  /* NOT READY IS A DIFFERENT BUTTON, NOT A FADED ONE.
     This was opacity:.6 on the filled teal analyze button — 2.84:1 for its
     label, on a control that is deliberately still LIVE (see pasteChanged:
     pressing it with too little text nudges the box rather than doing
     nothing). A disabled control may fall below AA; this one is not disabled,
     so it may not.
     It borrows the outline treatment .primary.detail already uses, so "not
     ready" reads as a hollow button and "ready" as a filled one — a clearer
     signal than dimness, and teal-ink is a colour the contrast suite checks. */
  .primary.soft{background:none;color:var(--teal-ink);
      border:1.5px solid color-mix(in srgb, var(--teal) 42%, transparent);box-shadow:none}

  /* account */
  .acc-plan-row{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-lg);padding:15px 16px;box-shadow:var(--e1),var(--edge);margin-bottom:18px}
  .acc-plan-row span{flex:1;display:block}
  .acc-plan-row small{display:block;font-size:12px;color:var(--ink-2)}
  .acc-plan-row b{font-size:16.5px;color:var(--teal-ink)}
  .mini-cta{background:var(--teal);color:var(--on-teal);border-radius:var(--r-sm);padding:8px 14px;
      font-size:13px;font-weight:700;white-space:nowrap}
  html[lang="ar"] .mini-cta{font-weight:400;font-size:15px}
  .acc-sec{border-top:1px solid var(--line);padding:16px 2px}
  .acc-sec h3{font-size:15px;color:var(--teal-ink);margin-bottom:8px}
  .acc-sec p{font-size:14px;color:var(--ink-2);line-height:1.8;margin-bottom:8px;
    white-space:pre-line}
  /* The erase control. Amber rather than red: this is the reader acting on
     their own data, deliberately, and painting it as danger would frame their
     own privacy decision as a mistake they are about to make. The confirm()
     is where the weight belongs. */
  .acc-wipe .wipe-what{font-size:13px;color:var(--ink);font-weight:700;margin-bottom:12px}
  html[lang="ar"] .acc-wipe .wipe-what{font-weight:400}
  .acc-sec .ghost.danger{color:var(--amber);border-color:var(--amber)}
  .acc-sec .ghost.danger:disabled{opacity:.45;cursor:default;
    color:var(--ink-2);border-color:var(--line)}
  /* The send button sits with copy and print, not above them: it is one more
     way out of the document, not a call to action on the reader's own letter. */
  .ghost.send{color:var(--teal-ink)}
  /* Same fold as the rights library, so the gesture is one the reader has
     already learnt somewhere else in this app. */
  .acc-fold{border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);
    margin:4px 0 10px;overflow:hidden}
  .acc-fold summary{list-style:none;cursor:pointer;padding:12px 14px;min-height:44px;
    display:flex;align-items:center;gap:10px;font-size:14px;font-weight:700;color:var(--teal-ink)}
  .acc-fold summary::-webkit-details-marker{display:none}
  .acc-fold summary::after{content:"";margin-inline-start:auto;width:8px;height:8px;flex:none;
    border-inline-end:2px solid var(--ink-2);border-block-end:2px solid var(--ink-2);
    transform:rotate(45deg);transition:transform var(--t-fast) var(--ease-out)}
  .acc-fold[open] summary::after{transform:rotate(-135deg)}
  .acc-fold > p{padding:0 14px 12px;margin:0}
  .acc-sec p.free{color:var(--green);}
  .acc-sec p.anchor{font-size:13px;color:var(--ink);background:var(--teal-soft);
      border-radius:var(--r-sm);padding:10px 12px;margin-top:4px}

  /* end-of-service calculator */
  .form{display:grid;gap:12px;margin-bottom:16px}
  .fld{display:block}
  /* The date a reader actually picked, spelled out, because the input above it
     is formatted by the browser rather than by this page. Quiet: it is a
     confirmation, not a warning. */
  .date-echo{display:block;margin-top:5px;font-size:13px;color:var(--ink-2);font-style:normal}
  html[lang="ar"] .date-echo{font-size:14px}
  .date-echo[hidden]{display:none}
  .fld>span{display:block;font-size:13px;color:var(--ink-2);margin-bottom:6px}
  .fld em{display:block;font-style:normal;font-size:12px;color:var(--ink-2);margin-top:5px}
  .fld input{width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
      padding:13px 15px;font:inherit;font-size:15px;color:var(--ink);box-shadow:var(--e1),var(--edge)}
  .fld input:focus{outline:2px solid var(--teal);border-color:transparent}
  .opts{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .opts button{border:1px solid var(--line);background:var(--card);border-radius:var(--r-md);
      padding:11px 10px;font-size:13px;color:var(--ink);box-shadow:var(--e1),var(--edge);transition:border-color .15s}
  .opts button.on{border-color:var(--teal);background:var(--teal-soft);color:var(--teal);font-weight:700}
  html[lang="ar"] .opts button.on{font-weight:400}
  /* THE FIRST OPTION SPANS THE ROW ONLY WHEN THAT LEAVES CLEAN PAIRS BELOW IT.
     Unconditionally, this turned every TWO-option group into one full-width
     button with a half-width orphan beside it — «محدد المدة» across the top and
     «غير محدد المدة» hanging off one side, which reads as a layout accident
     rather than a choice. :nth-last-child(odd) on the first child is true only
     when the group holds an odd number, so three options still render as one
     wide plus a pair (which is what the rule was written for) and two or four
     render as tidy rows. */
  .opts button:first-child:nth-last-child(odd){grid-column:1/-1}
  /* Seven termination options read as a list, not a keypad. */
  .opts.stack{grid-template-columns:1fr}
  .opts.stack button{text-align:start;padding:14px 14px;min-height:44px;line-height:1.45}
  .opts.stack button:first-child{grid-column:auto}

  /* ---------------------------------------------- termination assessment */
  .tq-steps{display:flex;gap:6px;margin-bottom:14px}
  .tq-steps i{flex:1;height:3px;border-radius:2px;background:var(--line);
    transition:background var(--t) var(--ease-out)}
  .tq-steps i.on{background:var(--teal)}
  .tq-skip{font-size:12px;color:var(--ink-2);text-align:center;margin-top:10px}
  .ev-honest,.ld-honest{font-size:12px;color:var(--ink-2);line-height:1.6;margin:12px 0 4px}
  .tm-secs{display:grid;gap:10px;margin-bottom:6px}
  .tm-sec{border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);padding:12px 14px}
  .tm-sec .hd{display:flex;align-items:center;gap:8px;justify-content:space-between}
  .tm-sec b{font-size:14px}
  .tm-sec p{font-size:13px;color:var(--ink-2);line-height:1.65;margin-top:6px}
  .tm-tag{font-size:12px;font-weight:700;padding:3px 9px;border-radius:999px;white-space:nowrap}
  html[lang="ar"] .tm-tag{font-weight:400}
  .tm-tag.ok{background:var(--green-bg);color:var(--green-ink)}
  .tm-tag.review{background:var(--amber-bg);color:var(--amber-ink)}
  .tm-tag.issue{background:var(--red-bg);color:var(--red-ink)}
  /* The one figure this screen exists to give, at the size the eos calculator
     already gives its own — the two screens answer the same question and only
     one of them used to look like it. */
  .tm-hero{background:var(--card);border:1px solid var(--line);border-radius:var(--r-2xl);
    padding:20px 18px 16px;margin-bottom:10px;text-align:center;box-shadow:var(--e2),var(--edge)}
  .tm-hero .lbl{font-size:13px;color:var(--ink-2)}
  .tm-hero .amt{font-family:var(--en);font-size:36px;font-weight:800;letter-spacing:-.03em;
    color:var(--teal-ink);line-height:1.15;margin-top:6px;font-variant-numeric:tabular-nums;direction:ltr}
  html[lang="ar"] .tm-hero .amt{font-family:var(--ar);font-weight:600;direction:rtl}
  .tm-hero .amt small{font-family:var(--en);font-size:15px;font-weight:700;letter-spacing:0;
    margin-inline-start:6px;color:var(--ink-2)}
  .tm-hero .alt{font-size:13px;color:var(--ink-2);margin-top:10px;padding-top:10px;
    border-top:1px solid var(--line)}
  .tm-hero .alt b{color:var(--ink);font-weight:700;white-space:nowrap}
  .tm-money{border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);padding:14px}
  .tm-money .r{display:flex;justify-content:space-between;gap:12px;align-items:baseline;
    padding:9px 0;border-bottom:1px solid var(--line)}
  .tm-money .r:last-of-type{border-bottom:0}
  .tm-money .r>span{font-size:14px;color:var(--ink-2)}
  .tm-money .r>b{font-size:14px;white-space:nowrap}
  /* Teal, not amber and not red. This says "the figure could be higher", and
     the product's warning colours would say the opposite — which is exactly
     the misreading it exists to prevent. Sits directly under the total. */
  .tm-rise{display:flex;align-items:flex-start;gap:9px;margin-top:10px;padding:11px 13px;
      background:var(--teal-soft);border-radius:var(--r-md);
      font-size:13px;line-height:1.65;color:var(--teal-ink)}
  .tm-rise .up{flex:none;width:18px;height:18px;margin-top:1px}
  .tm-rise .up svg{width:18px;height:18px}
  .tm-money .r.tot{border-top:2px solid var(--line);margin-top:4px;padding-top:12px}
  .tm-money .r.tot>span,.tm-money .r.tot>b{color:var(--ink);font-size:15px}
  /* The contested figure is separated by arithmetic; it has to be separated by
     eye too, or two identical rows read as one total split across two lines.
     Lighter rule, muted ink — present, checkable, and not the headline. */
  .tm-split-h{font-size:13px;font-weight:700;color:var(--ink-2);margin:14px 0 6px;
    padding-top:12px;border-top:1px dashed var(--line)}
  .tm-money .r.tot.soft{border-top-width:1px;margin-top:0}
  .tm-money .r.tot.soft>span,.tm-money .r.tot.soft>b{color:var(--ink-2);font-size:14px}
  .tm-money .src-line{margin:2px 0 8px}
  .tm-money .cap{font-size:12px;color:var(--ink-2);line-height:1.6;margin-top:12px}
  .tm-claims{display:grid;gap:10px}
  .tm-claim{border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);padding:12px 14px}
  .tm-claim b{font-size:14px;display:block;margin-bottom:6px}
  .tm-claim dl{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;font-size:13px;margin-top:6px}
  .tm-claim dt{color:var(--ink-2)}
  .tm-claim dd{color:var(--ink);line-height:1.55}
  .tm-claim .hd{display:flex;align-items:center;gap:8px;justify-content:space-between;margin-bottom:6px}
  .tm-claim .hd b{margin:0}
  .tm-gap{font-size:13px;color:var(--red-ink);line-height:1.6;margin-top:8px}
  .tm-off{font-size:12px;color:var(--ink-2);margin-top:4px}
  .tm-how details{border:1px solid var(--line);border-radius:var(--r-md);
    background:var(--card);margin-bottom:8px}
  .tm-how summary{padding:12px 14px;font-size:14px;cursor:pointer;min-height:44px;
    display:flex;align-items:center;list-style:none}
  .tm-how summary::-webkit-details-marker{display:none}
  .tm-how summary::after{content:"+";margin-inline-start:auto;color:var(--ink-2);font-size:19px}
  .tm-how details[open] summary::after{content:"−"}
  .tm-how p{padding:0 14px 12px;font-size:13px;color:var(--ink-2);line-height:1.65}
  .ai-agree{display:flex;gap:9px;align-items:flex-start;margin:10px 0;
    font-size:13px;line-height:1.6;min-height:44px}
  .ai-agree input{margin-top:3px;width:18px;height:18px;accent-color:var(--teal);flex:none}
  /* ASK. The two tiers must not be able to be mistaken for each other at a
     glance, so they differ in edge colour, header colour and the presence of
     a source block — not in one subtle word. A verified answer earns the same
     teal-edged treatment every other sourced claim in the app gets; an
     unverified one is amber-edged and carries its warning below the text
     rather than above it, where it would be scrolled past. */
  .ask-q{width:100%;min-height:88px;padding:11px 12px;border:1px solid var(--line);
    border-radius:var(--r-sm);background:var(--bg);color:var(--ink);font:inherit;
    font-size:14px;line-height:1.6;resize:vertical}
  .ask-q:focus{outline:2px solid var(--teal);outline-offset:1px}
  .ask-ctx{border-top:1px solid var(--line);margin-top:12px;padding-top:10px}
  .ask-q:disabled,#askGo:disabled{opacity:.45;cursor:not-allowed}
  .ask-ans{margin-bottom:12px}
  .ask-ans.verified{border-inline-start:3px solid var(--teal)}
  .ask-ans.verified .hd b{color:var(--teal-ink)}
  .ask-ans.unverified{border-inline-start:3px solid var(--amber-ink);background:var(--amber-bg)}
  /* Contract review reuses the SAME two tiers as the ask answers above, on
     purpose: a reader who has learned once what teal and amber mean here does
     not have to learn it again. */
  .cr-cite{display:flex;flex-wrap:wrap;gap:4px 8px;align-items:baseline;margin-top:8px;
           padding-inline-start:9px;border-inline-start:3px solid var(--teal);font-size:13px}
  .cr-cite b{color:var(--teal-ink)}
  .cr-cite span{color:var(--ink-2);font-size:12px}
  .cr-cite.unverified{border-inline-start-color:var(--amber-ink);background:var(--amber-bg);
                      padding:6px 9px;border-radius:0 8px 8px 0}
  .cr-cite.unverified b{color:var(--amber-ink)}
  .cr-clause{display:block;font-size:14px;color:var(--ink-2);font-weight:400;
             padding-inline-start:9px;border-inline-start:2px solid var(--line);
             margin-bottom:6px;font-style:italic}
  html[lang="ar"] .cr-clause{font-style:normal}
  .cr-terms{margin:8px 0 4px}
  .cr-terms>div{display:flex;justify-content:space-between;gap:12px;padding:7px 0;
                border-bottom:1px solid var(--line);font-size:14px}
  .cr-terms>div:last-child{border-bottom:0}
  .cr-terms span{color:var(--ink-2)}
  .cr-terms b{color:var(--ink);text-align:end}
  .ask-ans.unverified .hd b{color:var(--amber-ink)}
  .ask-body{font-size:14px !important;color:var(--ink) !important;margin-top:8px !important}
  .ask-src-h{font-size:12px !important;font-weight:700;margin-top:12px !important;
    text-transform:uppercase;letter-spacing:.04em}
  html[lang="ar"] .ask-src-h{text-transform:none;letter-spacing:0;font-weight:400}
  /* Teal, like every other place the app is standing on something solid —
     not the amber of the unverified tier. The quotes are the reader's own
     words and are set apart as quotation, not as our prose. */
  .ask-ans.contract .hd b{color:var(--teal-ink)}
  .src-line.doc-q{font-style:italic;color:var(--ink-2);border-inline-start:2px solid var(--teal);
      padding-inline-start:10px;margin:6px 0}
  .ask-unv{font-size:13px !important;margin-top:10px !important;color:var(--amber-ink) !important}
  .ask-ref{border-inline-start:3px solid var(--ink-2);margin-bottom:12px}
  /* Amber, matching every other "this is a limit of what we know" surface in
     the app rather than the red reserved for something being wrong. */
  .ai-cut{background:var(--amber-bg);border-radius:var(--r-md);padding:11px 13px;margin:10px 0 4px}
  .ai-cut b{display:block;color:var(--amber-ink);font-size:14px;margin-bottom:4px}
  .ai-cut p{font-size:13px;line-height:1.65;color:var(--ink-2)}
  .ai-find{border-top:1px solid var(--line);padding-top:10px;margin-top:10px}
  .ai-find b{display:block;font-size:14px;margin-bottom:4px}
  .ai-find p{font-size:13px;color:var(--ink-2);line-height:1.65}
  .ai-find.attention b{color:var(--red-ink)}
  .ai-find.review b{color:var(--amber-ink)}
  /* Neutral on purpose. An obligation gets the ink colour of ordinary text
     rather than a warning colour, because most of them are unremarkable and
     colouring them as problems would teach the reader to skip them. */
  .ai-find.duty b{color:var(--teal-ink)}
  .ai-summary{font-size:13px;color:var(--ink-2);line-height:1.65;margin:6px 0}
  .airv-reason{font-size:13px;color:var(--red-ink);line-height:1.65;margin:8px 0}
  .airv-c{border-top:1px solid var(--line);padding-top:10px;margin-top:10px}
  .airv-c .hd{display:flex;align-items:center;gap:8px;justify-content:space-between;margin-bottom:6px}
  .airv-c b{font-size:14px}
  .airv-detail{font-size:13px;color:var(--ink);line-height:1.65}
  .airv-note{font-size:12px;color:var(--ink-2);line-height:1.6;margin-top:4px}
  .rv-bar{height:3px;border-radius:2px;background:var(--line);overflow:hidden;margin-top:10px}
  .rv-bar i{display:block;height:100%;width:40%;background:var(--teal);
    animation:rvslide 1.1s var(--ease-move) infinite}
  @keyframes rvslide{0%{transform:translateX(-100%)}100%{transform:translateX(350%)}}
  @media (prefers-reduced-motion:reduce){ .rv-bar i{animation:none;width:100%} }
  .tm-steps{display:grid;gap:10px}
  .tm-step{border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);padding:14px}
  .tm-step .n{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
    border-radius:50%;background:var(--teal);color:var(--on-teal);font-size:12px;margin-bottom:8px}
  .tm-step b{display:block;font-size:14px;margin-bottom:4px}
  .tm-step p{font-size:13px;color:var(--ink-2);line-height:1.65}
  .tm-step button{margin-top:10px;min-height:44px}

  .eos-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-2xl);
      padding:24px 20px 18px;margin-top:16px;text-align:center;box-shadow:var(--e2),var(--edge)}
  .eos-card .lbl{font-size:13px;color:var(--ink-2)}
  .eos-card .amt{font-family:var(--en);font-size:36px;font-weight:800;letter-spacing:-.03em;
      color:var(--teal-ink);line-height:1.15;margin-top:6px;font-variant-numeric:tabular-nums;direction:ltr}
  html[lang="ar"] .eos-card .amt{font-family:var(--ar);font-weight:600;direction:rtl}
  .eos-card .amt small{font-family:var(--en);font-size:15px;font-weight:700;letter-spacing:0;margin-inline-start:6px;color:var(--ink-2)}
  .eos-card .svc{font-size:13px;color:var(--ink-2);margin-top:8px;padding-bottom:16px;border-bottom:1px solid var(--line)}
  .rows{display:grid;gap:9px;margin-top:16px;text-align:start}
  .rows .r{display:flex;align-items:baseline;gap:10px;font-size:14px;color:var(--ink-2)}
  .rows .r span{flex:1;min-width:0}
  .rows .r b{font-family:var(--en);color:var(--ink);font-variant-numeric:tabular-nums;font-weight:700;white-space:nowrap}
  html[lang="ar"] .rows .r b{font-family:var(--ar);font-weight:600}
  .rows .r.tot{border-top:1px solid var(--line);padding-top:10px;margin-top:2px;color:var(--ink);font-size:15px}
  .rows .r.tot b{color:var(--teal-ink);font-size:16.5px}
  .eos-note{font-size:12px;color:var(--ink-2);margin-top:14px;line-height:1.65;text-align:start}
  /* A figure the reader should check before believing. Amber, like every
     other "worth a pause" surface here — quiet enough not to cry wolf, loud
     enough to be seen beside a large confident number. */
  .eos-note.warn{color:var(--amber-ink);background:var(--amber-bg);border-radius:10px;
    padding:9px 11px;font-size:13px;margin-top:12px}

  /* termination triage */
  .triage{background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);
      padding:18px;margin-top:14px;box-shadow:var(--e1),var(--edge)}
  .triage h4{font-size:15px;color:var(--teal-ink);margin-bottom:12px}
  .tq{display:flex;align-items:center;gap:10px;margin-bottom:10px}
  .tq span{flex:1;font-size:14px;color:var(--ink)}
  .tq .yn{display:flex;gap:6px}
  .tq .yn button{border:1px solid var(--line);background:var(--sand);border-radius:999px;
    min-height:44px;display:inline-flex;align-items:center;justify-content:center;
      padding:6px 14px;font-size:13px;color:var(--ink-2);min-width:52px}
  .tq .yn button.on{background:var(--teal);border-color:var(--teal);color:var(--on-teal)}
  .verdict-box{border-radius:var(--r-lg);padding:14px 15px;margin-top:6px}
  .verdict-box.ok{background:var(--green-bg)} .verdict-box.warn{background:var(--amber-bg)}
  .verdict-box.act{background:var(--red-bg)}
  .verdict-box b{display:block;font-size:15px;color:var(--ink);margin-bottom:4px}
  .verdict-box p{font-size:13px;color:var(--ink-2);line-height:1.7}
  .clock{display:flex;gap:9px;align-items:flex-start;font-size:13px;color:var(--ink);
      background:var(--amber-bg);border-radius:var(--r-md);padding:11px 13px;margin-top:10px;line-height:1.65}
  .clock svg{flex:none;width:15px;height:15px;margin-top:3px;color:var(--amber)}

  /* case file */
  .claim-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-2xl);
      padding:20px 18px 16px;box-shadow:var(--e2),var(--edge);margin-bottom:20px}
  .claim-card h4{font-size:13px;color:var(--ink-2);font-weight:400;margin-bottom:12px}
  .claim-card .r{display:flex;align-items:baseline;gap:10px;font-size:14px;color:var(--ink-2);margin-bottom:9px}
  .claim-card .r span{flex:1}
  .claim-card .r b{font-family:var(--en);color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
  html[lang="ar"] .claim-card .r b{font-family:var(--ar)}
  .claim-card .r.tot{border-top:1px solid var(--line);padding-top:11px;margin-top:3px;color:var(--ink);font-size:15px}
  .claim-card .r.tot b{color:var(--teal-ink);font-size:19px;font-weight:800}
  html[lang="ar"] .claim-card .r.tot b{font-weight:600}
  .claim-card .mini{font-size:12px;color:var(--ink-2);line-height:1.6;margin:-3px 0 10px}
  .leave-in{display:flex;align-items:center;gap:10px;margin:4px 0 12px}
  .leave-in span{flex:1;font-size:13px;color:var(--ink-2)}
  .leave-in input{width:84px;background:var(--sand);border:1px solid var(--line);border-radius:var(--r-sm);
      padding:9px 11px;font:inherit;font-size:14px;color:var(--ink);text-align:center}
  .docs{display:grid;gap:9px;margin-bottom:16px}
  .doc{display:flex;align-items:center;gap:12px;width:100%;background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-md);padding:13px 15px;text-align:start;box-shadow:var(--e1),var(--edge);transition:border-color .15s}
  .doc .box{flex:none;width:22px;height:22px;border-radius:7px;border:2px solid var(--line);
      display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}
  .doc .box svg{width:12px;height:12px;opacity:0;color:var(--on-teal)}
  .doc.on{border-color:var(--teal)}
  .doc.on .box{background:var(--teal);border-color:var(--teal)}
  .doc.on .box svg{opacity:1}
  .doc span{flex:1;font-size:14px;color:var(--ink)}
  .ready{margin-bottom:16px}
  .ready .meter{height:6px;border-radius:6px;background:var(--line);overflow:hidden}
  .ready .meter i{display:block;height:100%;background:var(--teal);border-radius:6px;transition:width .35s cubic-bezier(.4,0,.2,1)}
  .ready .lbl{display:flex;justify-content:space-between;font-size:12px;color:var(--ink-2);margin-bottom:7px}

  /* plans */
  /* Informational, not an alarm. Teal like the rest of the interface, not
     the amber we reserve for "something is wrong with your contract" —
     borrowing the warning colour for a calendar date would cry wolf. */
  /* Quiet by design: the code route is for people who already paid, not a
     second call to action competing with the price ladder. */
  .redeem{margin-top:14px;text-align:center}
  .redeem[hidden]{display:none}
  .rd-open{min-height:44px;padding:8px 12px;font-size:13px;font-weight:700;
    color:var(--teal);text-decoration:underline;text-underline-offset:3px}
  .rd-open:hover{color:var(--teal-ink)}
  .rd-form{display:flex;gap:8px;margin-top:10px}
  .rd-form[hidden]{display:none}
  .rd-form input{flex:1;min-height:44px;padding:10px 14px;border-radius:var(--r-md);
    border:1px solid var(--line);background:var(--card);color:var(--ink);
    font-family:var(--en);font-size:15px;letter-spacing:.06em;text-align:center;
    text-transform:uppercase}
  .rd-form input:focus-visible{border-color:var(--teal)}
  .rd-go{min-height:44px;padding:10px 18px;border-radius:var(--r-md);
    background:var(--teal);color:var(--on-teal);font-size:14px;font-weight:700}
  .rd-msg{margin-top:9px;font-size:13px;line-height:1.6;color:var(--teal-ink)}
  .rd-msg[hidden]{display:none}
  .rd-msg.bad{color:var(--red-ink)}
  .mini.warn{color:var(--amber-ink);font-weight:700}

  .timely{background:var(--teal-soft);border:1px solid color-mix(in srgb, var(--teal) 24%, transparent);
    border-radius:var(--r-lg);padding:14px 16px;margin:0 0 16px}
  .timely[hidden]{display:none}
  .tm-txt{display:flex;flex-direction:column;gap:5px}
  .tm-txt b{font-size:14px;color:var(--teal-ink);line-height:1.5}
  .tm-txt span{font-size:13px;color:var(--ink-2);line-height:1.65}
  .tm-act{display:flex;gap:8px;margin-top:12px}
  .tm-go,.tm-x{min-height:44px;padding:9px 16px;border-radius:var(--r-md);
    font-size:14px;font-weight:700;transition:transform var(--t-fast) var(--ease-out)}
  .tm-go{background:var(--teal);color:var(--on-teal)}
  .tm-x{background:none;color:var(--ink-2);border:1px solid var(--line)}
  .tm-go:active,.tm-x:active{transform:scale(.97)}

  /* Install hint. Quieter than .timely on purpose — it is an offer, not news. */
  .install{display:flex;align-items:flex-start;gap:12px;background:var(--card);
    border:1px solid var(--line);border-radius:var(--r-lg);padding:13px 15px;margin:0 0 16px;
    box-shadow:var(--e1)}
  .install[hidden]{display:none}
  .ih-ic{flex:none;width:34px;height:34px;border-radius:999px;background:var(--teal-soft);
    display:flex;align-items:center;justify-content:center}
  .ih-ic svg{width:19px;height:19px}
  .ih-t{flex:1;display:flex;flex-direction:column;gap:3px;min-width:0}
  .ih-t b{font-size:14px;color:var(--ink);line-height:1.5}
  html[lang="ar"] .ih-t b{font-weight:600;font-size:15px}
  .ih-b{font-size:13px;color:var(--ink-2);line-height:1.65}
  .ih-x{flex:none;align-self:center;min-height:44px;padding:0 10px;background:none;
    color:var(--ink-2);font-size:13px;font-weight:700}
  .ih-x:active{transform:scale(.97)}

  /* A stated fact with a way to change it. It used to sit above the doors on
     home, where it was a decision asked before any content and already
     answered in onboarding; it now lives in Account. Full 44px target. */
  .nat-chip{display:flex;align-items:center;gap:6px;width:100%;min-height:44px;
    padding:6px 2px;margin:0 0 10px;background:none;border:0;text-align:start;
    font-size:13px;color:var(--ink-2);line-height:1.6}
  .nat-chip[hidden]{display:none}
  .nat-chip b{color:var(--teal-ink);font-size:13px;font-weight:800}
  .nat-chip .nat-swap{margin-inline-start:auto;color:var(--teal);font-weight:700;
    text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
  .nat-chip:hover .nat-swap{color:var(--teal-ink)}
  .nat-chip:active{opacity:.7}
  .acc-nat .nat-chip{margin:0}

  /* The one question the intake screen asks before it reads anything. A
     checkbox rather than a segmented control: there is a default (derived from
     the door), and this only corrects it. */
  .signed-ask{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;
    padding:10px 12px;margin:0 0 14px;background:var(--card);border:1px solid var(--line);
    border-radius:var(--r-sm);text-align:start;font-size:14px;color:var(--ink-2);line-height:1.5}
  .signed-ask .sa-box{flex:none;width:20px;height:20px;border-radius:6px;
    border:1.5px solid var(--line);background:var(--bg);display:flex;align-items:center;
    justify-content:center;color:transparent;transition:background var(--t-fast),border-color var(--t-fast)}
  .signed-ask .sa-box svg{width:12px;height:12px}
  .signed-ask.on{border-color:var(--teal);color:var(--ink)}
  .signed-ask.on .sa-box{background:var(--teal);border-color:var(--teal);color:var(--on-teal)}
  .signed-ask:active{transform:scale(.99)}
  .seg{display:flex;gap:4px;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:4px;margin-bottom:16px}
  .seg button{flex:1;border-radius:999px;padding:9px;font-size:14px;color:var(--ink-2);font-weight:700;
    min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  html[lang="ar"] .seg button{font-weight:400;font-size:15px}
  .seg button.on{background:var(--teal);color:var(--on-teal)}
  .seg .save{font-size:12px;background:var(--amber-bg);color:var(--amber-ink);border-radius:999px;padding:1px 7px;margin-inline-start:6px}
  .plan-cards{display:grid;gap:12px}
  .pcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r-2xl);padding:20px 18px 17px;position:relative;box-shadow:var(--e1),var(--edge);transition:box-shadow .2s}
  .pcard.hi{border-color:var(--teal);box-shadow:var(--e2),var(--edge)}
  .pcard.biz{border-color:var(--amber)}
  .pcard .tag{position:absolute;top:-9px;inset-inline-start:18px;font-size:12px;font-weight:700;
      background:var(--teal);color:var(--on-teal);border-radius:999px;padding:2px 10px}
  html[lang="ar"] .pcard .tag{font-weight:400;font-size:12px}
  .pcard.biz .tag{background:var(--amber);color:var(--on-teal)}
  .pcard h3{font-size:19px;color:var(--teal-ink)}
  .pcard .d{font-size:13px;color:var(--ink-2);margin-top:2px}
  .pcard .price{margin-top:12px;display:flex;align-items:baseline;gap:5px;flex-wrap:wrap}
  .pcard .price b{font-family:var(--en);font-size:24px;color:var(--ink);font-variant-numeric:tabular-nums}
  .pcard .price i{font-style:normal;font-size:13px;color:var(--ink-2)}
  /* The scan's edge. Deliberately quiet — it sits under a real finding, and a
     loud upsell directly beneath a genuine warning reads as using the warning
     to sell, which is the thing this whole shape exists to avoid. */
  .scan-lock{border:1px dashed var(--line);border-radius:14px;padding:16px;
             margin-top:12px;background:var(--card)}
  .scan-lock b{display:block;font-size:15px;margin-bottom:6px}
  .scan-lock p{margin:0 0 8px;font-size:14px;color:var(--ink-2);line-height:1.6}
  .scan-lock .scan-left{font-size:13px;color:var(--ink-2)}
  /* THE BUTTON THAT SELLS THE PRODUCT, and it had no button styling at all.
     `.cta` has no base rule in this stylesheet — it is only ever styled inside
     `.pcard` — so here it inherited nothing: no background, no padding, no
     height. Measured 27px tall with 0 padding, rendering as a line of teal
     text in the middle of the lock panel. The single most important control in
     the funnel did not look like a control.

     Matched to `.primary`, which is what every other primary action in the app
     uses, rather than inventing a fourth button style. */
  .scan-lock .cta{
    margin-top:12px;width:100%;background:var(--teal);color:var(--on-teal);
    font-weight:700;font-size:16.5px;border-radius:var(--r-lg);padding:15px 16px;
    min-height:48px;box-shadow:var(--e2);transition:opacity .15s,box-shadow .18s;
    /* The English label wraps to two lines at 390px and broke as
       "…review — 199" / "SAR", splitting the price across the fold. balance
       moves the break to the em dash instead. Arabic fits on one line and is
       unaffected. */
    text-wrap:balance;
  }
  html[lang="ar"] .scan-lock .cta{font-weight:400;font-size:16.5px}
  .scan-lock .cta:hover{box-shadow:var(--e3)}
  .scan-lock .cta:active{transform:scale(.985)}
  .scan-lock .cta:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
  .au-sep{display:flex;align-items:center;gap:10px;margin:14px 0 2px;
          color:var(--ink-2);font-size:13px}
  .au-sep::before,.au-sep::after{content:"";flex:1;height:1px;background:var(--line)}
  .au-mail{display:flex;flex-direction:column;gap:8px;margin-top:10px}
  .au-lab{font-size:13px;color:var(--ink-2)}
  .au-mail input{font:inherit;padding:11px 12px;border-radius:12px;
                 border:1px solid var(--line);background:var(--card);color:var(--ink)}
  .au-btn.mail{justify-content:center}
  .au-again{background:none;border:0;color:var(--teal-ink);font:inherit;
            font-size:13px;text-decoration:underline;cursor:pointer;padding:4px}
  .acc-pack{margin:6px 0 0;font-size:13px;color:var(--ink-2)}
  /* The «قريبًا» badge and the hidden radio already say this one is not on
     offer; the fade only made the words harder to read (3.98 on a card). */
  .plan.soon{cursor:default}
  .plan.soon .radio{visibility:hidden}
  .pcard ul{list-style:none;margin-top:14px;display:grid;gap:7px}
  .pcard li{font-size:13px;color:var(--ink);display:flex;gap:9px;align-items:flex-start;line-height:1.55}
  .pcard li svg{flex:none;width:15px;height:15px;margin-top:3px;color:var(--green)}
  .pcard li.off{color:var(--ink-2)}
  .pcard li.off svg{color:var(--ink-2)}
  .pcard .cta{margin-top:15px;width:100%;border-radius:14px;padding:12px;font-weight:700;font-size:15px;
      background:var(--teal);color:var(--on-teal)}
  html[lang="ar"] .pcard .cta{font-weight:400;font-size:16.5px}
  .pcard.biz .cta{background:var(--amber)}
  .pcard .cta.owned{background:var(--teal-soft);color:var(--teal)}

  /* business workspace */
  .biz-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}
  .trial-chip{display:inline-block;margin-top:5px;font-size:12px;color:var(--amber-ink);
      background:var(--amber-bg);border-radius:999px;padding:2px 10px}
  .biz-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin-bottom:20px}
  .biz-stats .st{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:15px 8px;text-align:center;box-shadow:var(--e1),var(--edge)}
  .biz-stats .st b{display:block;font-family:var(--en);font-size:24px;color:var(--teal-ink);font-variant-numeric:tabular-nums}
  .biz-stats .st.warn b{color:var(--amber)}
  .biz-stats .st span{font-size:12px;color:var(--ink-2);line-height:1.4;display:block;margin-top:2px}
  .biz-h[hidden]{display:none}
  .biz-h{font-size:16.5px;color:var(--teal-ink);margin:4px 2px 9px}
  .biz-note{font-size:13px;color:var(--ink-2);margin:-4px 2px 10px;line-height:1.6}
  .biz-list{display:grid;gap:9px;margin-bottom:20px}
  .brow{display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);
      border-radius:var(--r-lg);padding:13px 14px;text-align:start;width:100%;box-shadow:var(--e1),var(--edge)}
  .brow .sc{flex:none;width:42px;height:42px;border-radius:12px;display:flex;align-items:center;justify-content:center;
      font-family:var(--en);font-weight:800;font-size:15px;font-variant-numeric:tabular-nums}
  .brow .sc.great{background:var(--green-bg);color:var(--green)}
  .brow .sc.good{background:var(--teal-soft);color:var(--teal)}
  .brow .sc.fair{background:var(--amber-bg);color:var(--amber-ink)}
  .brow .sc.poor{background:var(--red-bg);color:var(--red)}
  .brow .tx{flex:1;min-width:0}
  .brow b{display:block;font-size:14px;color:var(--ink)}
  .brow span{font-size:12px;color:var(--ink-2)}
  .brow .status{font-size:12px;border-radius:999px;padding:2px 9px;white-space:nowrap;
      background:var(--teal-soft);color:var(--teal)}
  .brow .status.redline{background:var(--amber-bg);color:var(--amber-ink)}
  .seats{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:8px}
  .seat{width:38px;height:38px;border-radius:999px;background:var(--teal-soft);color:var(--teal);
      display:flex;align-items:center;justify-content:center;font-family:var(--en);font-weight:800;font-size:13px}
  .seat.add{background:none;border:1px dashed var(--line);color:var(--ink-2);font-weight:400;font-size:19px}
  .seats .n{font-size:13px;color:var(--ink-2);margin-inline-start:auto}

  /* AI legal assistant */
  .assist-entry{display:flex;align-items:center;gap:12px;width:100%;background:var(--card);
      border:1px solid var(--line);border-radius:var(--r-lg);padding:13px 15px;margin-top:14px;text-align:start;box-shadow:var(--shadow)}
  .assist-entry .ic{flex:none;width:38px;height:38px;border-radius:var(--r-sm);background:var(--teal);box-shadow:var(--e1);
      display:flex;align-items:center;justify-content:center}
  .assist-entry .ic svg{width:20px;height:20px}
  .assist-entry b{display:block;font-size:15px;color:var(--ink)}
  .assist-entry span span{font-size:13px;color:var(--ink-2)}
  .assist-entry .go{margin-inline-start:auto;color:var(--teal);display:flex}

  .caps{display:flex;gap:8px;overflow-x:auto;padding:2px 0 12px;scrollbar-width:none}
  .caps::-webkit-scrollbar{display:none}
  /* 44px, the same touch minimum the rest of the app holds to. These sat at
     37px — the one control group in the product below it, and the first
     thing a reader taps on the assistant screen. Measured at 390x844 and
     430x932 in both languages. */
  .caps button{flex:none;font-size:13px;color:var(--teal);background:var(--teal-soft);
    min-height:44px;display:inline-flex;align-items:center;
      border:1px solid transparent;border-radius:999px;padding:7px 13px;white-space:nowrap}
  .caps button:hover{border-color:var(--teal)}

  .chat{flex:1;display:flex;flex-direction:column;gap:10px;padding:4px 0 12px;min-height:220px}
  .msg{max-width:86%;border-radius:var(--r-lg);padding:12px 14px;font-size:14px;line-height:1.75;white-space:pre-line}
  .msg.bot{align-self:flex-start;background:var(--card);border:1px solid var(--line);border-start-start-radius:6px;color:var(--ink);box-shadow:var(--e1),var(--edge)}
  .msg.user{align-self:flex-end;background:var(--teal);color:var(--on-teal);border-start-end-radius:6px;box-shadow:var(--e1)}
  .msg .refs{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
  .msg .ref{font-size:12px;color:var(--teal);background:var(--teal-soft);border-radius:999px;padding:3px 10px}
  .msg .inline-cta{margin-top:11px;width:100%;background:var(--teal);color:var(--on-teal);
      border-radius:12px;padding:10px;font-size:14px;font-weight:700}
  html[lang="ar"] .msg .inline-cta{font-weight:400;font-size:15px}
  .typing{display:flex;gap:4px;align-items:center}
  .typing i{width:6px;height:6px;border-radius:99px;background:var(--ink-2);animation:blink 1s infinite}
  .typing i:nth-child(2){animation-delay:.15s} .typing i:nth-child(3){animation-delay:.3s}
  @keyframes blink{0%,60%,100%{opacity:.25}30%{opacity:1}}

  .quota{font-size:12px;color:var(--ink-2);text-align:center;padding:2px 0 8px}
  .quota.gate{background:var(--amber-bg);border:1px solid var(--amber);border-radius:14px;
      padding:14px;color:var(--ink);font-size:14px;text-align:center}
  .quota.gate b{display:block;font-size:15px;margin-bottom:4px}
  .quota.gate button{margin-top:10px;width:100%;background:var(--teal);color:var(--on-teal);
      border-radius:12px;padding:11px;font-weight:700;font-size:14px}
  html[lang="ar"] .quota.gate button{font-weight:400;font-size:15px}

  .ask-bar{display:flex;gap:8px;align-items:center}
  .ask-bar input{flex:1;background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
      padding:13px 15px;font:inherit;font-size:14px;color:var(--ink);min-width:0}
  .ask-bar input:focus{outline:2px solid var(--teal);border-color:transparent}
  .ask-send{flex:none;width:46px;height:46px;border-radius:var(--r-md);background:var(--teal);
      display:flex;align-items:center;justify-content:center}
  .ask-send svg{width:20px;height:20px}
  html[dir="rtl"] .ask-send svg{transform:scaleX(-1)}
  .ask-bar input:disabled,.ask-send:disabled{opacity:.45}

  /* reminder timeline */
  /* Reminders are a quiet utility, not a second offer — flatter than the
     paid letter card so the two never compete for the same attention. */
  .track-tease{display:flex;align-items:center;gap:11px;width:100%;background:none;border:1px solid var(--line);border-radius:var(--r-md);padding:11px 14px;margin-top:8px;text-align:start}
  .track-tease .bell{flex:none;width:30px;height:30px;border-radius:9px;background:var(--teal-soft);display:flex;align-items:center;justify-content:center}
  .track-tease .bell svg{width:16px;height:16px;stroke:var(--teal)}
  .track-tease b{display:block;font-size:14px;color:var(--ink)}
  .track-tease span{font-size:12px;color:var(--ink-2)}
  .track-tease .go{margin-inline-start:auto;color:var(--teal);display:flex}
  .track-tease.solo{background:var(--teal-soft);border-color:var(--teal);padding:14px 16px;box-shadow:var(--shadow)}
  .track-tease.solo b{font-size:15px}
  .track-tease.solo .bell{background:var(--teal);width:36px;height:36px}
  .track-tease.solo .bell svg{stroke:var(--on-teal)}

  /* One recommended next step, and the rest quiet. Demoted blocks keep their
     full hit area and stay perfectly usable — this is emphasis, not a gate. */
  /* Reading the clauses is a drill-down, not a next step. As a solid teal
     button it outweighed the step we actually recommend, which defeats the
     point of recommending one. Same size and hit area, less shout. */
  .primary.detail{background:none;color:var(--teal-ink);
    border:1.5px solid color-mix(in srgb, var(--teal) 42%, transparent);box-shadow:none}
  .primary.detail:hover{background:var(--teal-soft)}

  .is-next{position:relative;box-shadow:0 0 0 2px color-mix(in srgb, var(--band) 45%, transparent), var(--e2)}
  /* Desaturation alone. The .62 opacity took ordinary body text to 3.71 while
     saturate() does nearly all the de-emphasising work and costs almost no
     luminance contrast, which is the half that matters for reading. */
  .demoted{filter:saturate(.55)}
  .demoted:hover,.demoted:focus-within{opacity:1;filter:none}
  .letter-tease.demoted{background:none;border-color:var(--line)}
  .escalate.demoted{background:none;border-color:var(--line)}
  /* The chip lives on blocks both inside and outside the score card, so it
     cannot borrow --band, which is card-scoped. It takes its pair from the
     result screen instead, using the same bg/ink combinations already
     contrast-checked for the decision band. The parent selectors are needed
     to outrank ".track-tease span" and ".letter-tease span". */
  #screen-result{--nx-bg:var(--teal-soft);--nx-ink:var(--teal-ink)}
  #screen-result[data-decision="safe"]{--nx-bg:var(--green-bg);--nx-ink:var(--green-ink)}
  #screen-result[data-decision="negotiate"]{--nx-bg:var(--amber-bg);--nx-ink:var(--amber-ink)}
  #screen-result[data-decision="lawyer"]{--nx-bg:var(--red-bg);--nx-ink:var(--red-ink)}
  .letter-tease .next-chip,.track-tease .next-chip,.escalate .next-chip,.next-chip{
    position:absolute;top:-9px;inset-inline-start:14px;
    background:var(--nx-bg);color:var(--nx-ink);
    border:1px solid color-mix(in srgb, var(--nx-ink) 35%, transparent);
    border-radius:999px;padding:2px 9px;font-size:10.5px;font-weight:800;
    letter-spacing:.02em;white-space:nowrap;line-height:1.6}
  @media (prefers-reduced-motion:no-preference){
    .is-next{transition:box-shadow var(--t) var(--ease-out)}
    .demoted{transition:opacity var(--t-fast) var(--ease-out),filter var(--t-fast) var(--ease-out)}
  }
  .home-plans{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin-top:4px;
      color:var(--ink-2);font-size:13px;padding:10px;border-radius:var(--r-sm)}
  .home-plans:hover{color:var(--teal)}
  /* Secondary utilities sit quietly below the primary act, in one rhythm. */
  .home-reminders{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:10px;width:100%;
      color:var(--ink-2);font-size:14px;font-weight:700;background:none;border:1px solid var(--line);
      border-radius:var(--r-md);padding:12px;transition:color .15s,border-color .15s}
  .home-reminders:hover{color:var(--teal);border-color:var(--teal)}
  html[lang="ar"] .home-reminders{font-weight:400;font-size:15px}

  .timeline{position:relative;margin:6px 0 20px;padding-inline-start:26px}
  .timeline::before{content:"";position:absolute;inset-block:10px;inset-inline-start:8px;width:2px;background:var(--line);border-radius:2px}
  .tl-item{position:relative;margin-bottom:14px}
  .tl-item .node{position:absolute;inset-inline-start:-26px;top:14px;width:18px;height:18px;border-radius:99px;border:3px solid var(--sand);display:flex;align-items:center;justify-content:center}
  .tl-item.info .node{background:var(--teal)} .tl-item.action .node{background:var(--amber)} .tl-item.deadline .node{background:var(--red)}
  .tl-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px 16px;box-shadow:var(--e1),var(--edge)}
  .tl-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .tl-date{font-size:13px;font-weight:700;color:var(--teal-ink);background:var(--sand);border:1px solid var(--line);border-radius:999px;padding:2px 10px;white-space:nowrap}
  html[lang="ar"] .tl-date{font-weight:400}
  .tl-rel{font-size:12px;color:var(--ink-2)}
  .tl-doc{margin-inline-start:auto;font-size:12px;font-weight:700;color:var(--teal);background:var(--teal-soft);border-radius:999px;padding:2px 9px;white-space:nowrap}
  html[lang="ar"] .tl-doc{font-weight:400;font-size:12px}
  .tl-card h4{font-size:15px;color:var(--ink);margin-top:6px}
  .tl-card p{font-size:13px;color:var(--ink-2);line-height:1.6;margin-top:2px}
  .tl-empty{text-align:center;color:var(--ink-2);font-size:14px;padding:34px 12px;background:var(--card);border:1px dashed var(--line);border-radius:18px}
  .tl-note{display:flex;align-items:center;justify-content:center;gap:8px;font-size:12px;color:var(--ink-2);margin-bottom:16px}
  .tl-export{margin-top:22px;padding:18px;background:var(--card);border:1px solid var(--line);
    border-radius:18px;box-shadow:var(--e1);text-align:center}
  .tl-export[hidden]{display:none}
  .tl-export-h{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:12px}
  .tl-export-b{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
  .tl-export-b button{flex:1 1 140px;min-height:44px;padding:11px 16px;border-radius:var(--r-md);
    border:1px solid var(--line);background:var(--bg);color:var(--teal-ink);
    font-size:14px;font-weight:700;
    transition:transform var(--t-fast) var(--ease-out),background var(--t-fast) var(--ease-out)}
  .tl-export-b button:hover{background:var(--teal-soft)}
  .tl-export-b button:active{transform:scale(.97)}
  .tl-export-n{margin-top:12px;font-size:12px;color:var(--ink-2);line-height:1.5}
  /* WAS .dot-on: a 30x18 pill with a knob, which is a toggle switch drawn in
     the ON position. It was not interactive and there was no service behind
     it — the reminders come from an .ics file the reader exports, fired by
     their own calendar. A control that looks enabled is a claim, and this one
     sat directly beside the sentence making it. Replaced by the calendar glyph
     the sentence now names. */
  .tl-note .tl-cal{display:flex;flex:none;color:var(--teal)}
  .tl-note .tl-cal svg{width:18px;height:18px}

  /* feedback */
  .feedback{background:none;border-top:1px solid var(--line);border-radius:0;padding:16px 10px 4px;margin-top:18px;text-align:center}
  .fb-q{font-size:14px;color:var(--ink-2)}
  .fb-btns{display:flex;justify-content:center;gap:14px;margin-top:12px}
  .fb-btns button{width:46px;height:46px;border-radius:999px;background:var(--card);border:1px solid var(--line);display:flex;align-items:center;justify-content:center;transition:border-color .15s,background .15s}
  .fb-btns button:hover{border-color:var(--teal)}
  .fb-btns svg{width:22px;height:22px}
  .fb-comment{margin-top:14px}
  .fb-comment textarea{min-height:72px;font-size:14px}
  .fb-comment .primary{margin-top:10px;padding:12px;font-size:15px}
  .fb-thanks{display:flex;align-items:center;justify-content:center;gap:10px;color:var(--ink);font-size:15px;padding:6px 0}
  .fb-thanks .tick{flex:none;width:28px;height:28px;border-radius:999px;background:var(--green);display:flex;align-items:center;justify-content:center}
  .fb-thanks .tick svg{width:14px;height:14px}

  /* clauses */
  .clause{background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);margin-bottom:12px;overflow:hidden;box-shadow:var(--e1),var(--edge)}
  .clause .head{display:flex;align-items:center;gap:10px;padding:13px 16px}
  .clause .stripe{flex:none;width:10px;height:10px;border-radius:99px}
  .clause h4{font-size:15px;color:var(--ink);flex:1}
  /* The reader's OWN sentence is marked apart from an authored sample quote:
     teal edge and a label. That difference is the whole point — a quote from
     their document turns an opinion into a pointer. */
  .quote[data-own]{border-inline-start-color:var(--teal)}
  .quote[data-own]::before{content:attr(data-label);display:block;font-style:normal;
    font-size:10.5px;letter-spacing:.04em;color:var(--teal-ink);
    font-weight:700;margin-bottom:4px}
  .flag .quote{margin:0 0 10px;padding:10px 14px;background:var(--sand);
    border-inline-start:3px solid var(--line);border-radius:8px;font-size:13px;
    color:var(--ink-2);line-height:1.7;font-style:italic}
  .clause .quote{margin:0 16px;padding:10px 14px;background:var(--sand);border-inline-start:3px solid var(--line);border-radius:8px;font-size:13px;color:var(--ink-2);line-height:1.7;font-style:italic}
  .clause .plain{padding:10px 16px 4px;font-size:14px;color:var(--ink);line-height:1.75}
  .clause .act{margin:8px 16px 14px;display:inline-block;font-size:13px;font-weight:700;border-radius:999px;padding:4px 12px}
  .clause.red .stripe{background:var(--red)} .clause.red .act{background:var(--red-bg);color:var(--red)}
  .clause.amber .stripe{background:var(--amber)} .clause.amber .act{background:var(--amber-bg);color:var(--amber-ink)}
  .clause.green .stripe{background:var(--green)} .clause.green .act{background:var(--green-bg);color:var(--green-ink)}
  .section-title{font-size:19px;color:var(--teal-ink);margin:6px 2px 14px}
  /* The situation chooser. Cards, not a dashboard: each one names a moment a
     reader is actually in, and goes straight to the flow for it. */
  .sit{margin:18px 0 22px}
  .sit-grid{display:flex;flex-direction:column;gap:9px}
  .sit-card{display:flex;align-items:center;gap:12px;width:100%;background:var(--card);
    border:1px solid var(--line);border-radius:var(--r-md);padding:13px 14px;text-align:start;
    box-shadow:var(--e1);cursor:pointer;min-height:60px}
  .sit-card .ic{flex:none;width:34px;height:34px;border-radius:var(--r-sm);background:var(--teal-bg);
    display:flex;align-items:center;justify-content:center}
  .sit-card .ic svg{width:19px;height:19px}
  .sit-card b{display:block;font-size:15px;color:var(--ink)}
  .sit-card span span{font-size:13px;color:var(--ink-2);line-height:1.5}
  .sit-card .go{margin-inline-start:auto;color:var(--teal);display:flex}
  .sit-card:active{transform:scale(.985);box-shadow:var(--e1)}
  .sit-u{margin-top:12px;border:1px solid var(--line);border-radius:var(--r-md);
    background:var(--card);padding:13px 14px}
  .sit-u p{font-size:14px;font-weight:700;margin-bottom:10px}
  html[lang="ar"] .sit-u p{font-weight:400}
  .sit-u-acts{display:flex;gap:9px;flex-wrap:wrap}
  .sit-u-acts .ghost{flex:1 1 auto;min-height:46px;font-size:14px}
  /* NO TWO-COLUMN RULE KEYED TO THE WINDOW. There used to be one at 600px,
     and it was the worst thing about the app on a laptop: it fired on window
     width while the frame stayed 440px, so the eight doors rendered at 199px
     each on a 1440px screen against 354px on a 390px phone — the front door of
     the product, 44% narrower on the bigger screen. The doors are one per row
     wherever the column is a column, and a grid only where the page is a page,
     which is the desktop block at the end of this file. */
  /* THE PHONE READER GETS TOLD WHAT THIS IS, TOO.
     This was display:none below 900px on the reasoning that a hero would push
     the doors under the fold. Measured, that was wrong about the cost: the
     desktop hero is ~250px, but set at phone scale it is 81px and takes one
     door off the first screenful — 6 of 8 become 5 on a 390x844. So a
     signed-out stranger on a phone, who is most of this market and all of its
     distressed readers, was landing on a greeting and eight identically
     weighted cards with no statement anywhere of what Wodouh is or who it is
     for. Eighty-one pixels is a cheap price for the sentence that answers it.
     19px and 14px are both on the nine-step scale; desktop.css raises them. */
  /* A cap that fired reads as a correction, not as a hint. */
  .cap-note{color:var(--amber);font-weight:700}
  html[lang="ar"] .cap-note{font-weight:400}
  .hm-hero{display:block;margin:10px 0 14px;text-align:center}
  .hm-hero .hm-hero-h{font-size:19px;color:var(--teal-ink);line-height:1.45;text-wrap:balance}
  .hm-hero p{margin-top:8px;color:var(--ink-2);font-size:14px}
  /* THE UPLOAD ROW. Same height as a door on purpose: it earns its place at
     the top of the screen by being FIRST and by being the only teal thing on
     it, not by being taller. Making it a drop zone would have cost roughly
     three doors of fold, which is the trade the situation chooser was built to
     avoid — see hm_up in the copy. */
  .hm-up{display:flex;align-items:center;gap:12px;width:100%;background:var(--teal);
    border:1px solid var(--teal);border-radius:var(--r-md);padding:13px 14px;text-align:start;
    box-shadow:var(--e1);cursor:pointer;min-height:60px;color:var(--on-teal)}
  .hm-up .ic{flex:none;width:34px;height:34px;border-radius:var(--r-sm);
    background:color-mix(in srgb, var(--on-teal) 16%, transparent);
    display:flex;align-items:center;justify-content:center;color:var(--on-teal)}
  .hm-up .ic svg{width:19px;height:19px}
  .hm-up b{display:block;font-size:15px;color:var(--on-teal)}
  .hm-up .tx span{font-size:13px;color:var(--on-teal);line-height:1.5}
  .hm-up .go{margin-inline-start:auto;color:var(--on-teal);display:flex}
  .hm-up:active{transform:scale(.985);box-shadow:var(--e1)}
  /* The money boundary and the privacy answer, rescued from two deleted
     onboarding cards. Quiet by design — they answer objections rather than
     make a claim, and a reader who is not asking should be able to skim past
     them to the doors. */
  .hm-up-note{margin:7px 2px 16px;font-size:12px;color:var(--ink-2);line-height:1.5}
  /* Only ever drawn where the split gives it a column of its own to fill. */
  .eos-pre{display:none}
  /* Accounts. Two buttons, brand-styled, nothing else competing. */
  .au-acts{display:flex;flex-direction:column;gap:11px;margin:20px 0 14px}
  .au-btn{display:flex;align-items:center;justify-content:center;gap:11px;width:100%;
    min-height:54px;border-radius:var(--r-md);border:1px solid var(--line);
    background:var(--card);color:var(--ink);font:inherit;font-size:16.5px;font-weight:700;
    box-shadow:var(--e1);cursor:pointer}
  html[lang="ar"] .au-btn{font-weight:400}
  .au-btn svg{width:19px;height:19px;flex:none}
  .au-btn:active{transform:scale(.985)}
  .au-btn.apple{background:var(--ink);color:var(--bg);border-color:var(--ink)}
  /* A sign-in method that is coming but not here. It must read as unavailable
     BEFORE it is pressed — a control that looks live and then refuses is the
     navigation equivalent of a locked door with no sign on it.
     Unavailability is drawn structurally rather than with opacity: a dashed
     edge, no fill, no shadow. The old rule faded the whole button to .55,
     which said "off" but also pushed the label and the قريبًا badge — the two
     pieces of text a reader most needs here — under the AA contrast floor. */
  .au-btn.soon{cursor:default;background:transparent;color:var(--ink-2);
               border-style:dashed;border-color:var(--line);box-shadow:none;
               font-weight:400}
  .au-btn.soon:active{transform:none}
  .au-btn .badge{display:inline-block;font-size:12px;font-weight:700;color:var(--amber-ink);
                 background:var(--amber-bg);border-radius:99px;padding:1px 8px;
                 margin-inline-start:6px;vertical-align:middle}
  .au-skip{text-align:center;cursor:pointer;text-decoration:underline;margin-top:4px}
  .free-now{background:var(--green-bg);border-radius:var(--r-md);padding:12px 14px;margin:0 0 14px}
  .free-now b{display:block;color:var(--teal-ink);font-size:15px;margin-bottom:4px}
  .free-now p{font-size:13px;line-height:1.65;color:var(--ink-2)}
  .free-now[hidden]{display:none}
  /* Deliberately not styled as a fourth sign-in button: it is the one control
     here that does NOT ask for an identity, and it should not read as another
     row in the same list. Full width and 44px tall so it is a real target. */
  /* A BORDERED CONTROL, not underlined text. It is the only way past this
     screen for someone who does not want an account, and as a grey underlined
     line under three solid buttons and a divider it read as fine print — on a
     phone it sat below the fold. It stays visually quieter than the sign-in
     buttons, because it is the second choice and not the first, but it is
     unmistakably a thing you can press. */
  .au-free{display:block;width:100%;min-height:48px;margin:16px 0 2px;padding:12px;
           background:none;border:1.5px solid var(--teal);border-radius:var(--r-md);
           color:var(--teal);font-size:14px;font-weight:700;cursor:pointer;text-align:center}
  .au-free:hover{background:var(--teal-soft)}
  html[lang="ar"] .au-free{font-size:15px;font-weight:400}
  .au-what{margin-top:18px}
  .au-err{margin-top:12px;font-size:13px;color:var(--red-ink)}
  .ph-l{display:block;font-size:13px;font-weight:700;margin-bottom:7px}
  html[lang="ar"] .ph-l{font-weight:400}
  .ph-in{min-height:52px;direction:ltr;text-align:start;font-size:16.5px}
  /* ---------------------------------------------------------- [hidden]
   *
   * THE FLOOR. `hidden` is how this app turns features off — an unconfigured
   * AI, a dark paywall, a lawyer desk with no lawyer — and it did not work.
   *
   * The attribute's display:none comes from the USER AGENT stylesheet, and any
   * author rule that sets display on a class beats it. `.fld{display:block}`
   * alone defeated it on six elements, three of which were promises the app
   * cannot keep: a refund guarantee while payments are dark, a lawyer desk
   * with no lawyer, and two doors to an AI that is not deployed. Every test
   * passed throughout, because they all read el.hidden — the attribute, which
   * was set correctly — rather than what the reader actually sees.
   *
   * !important is load-bearing, not laziness: the whole failure is an author
   * rule winning, so the fix has to outrank one. Ten one-off
   * `.x[hidden]{display:none}` patches already exist above, added one at a
   * time as someone noticed each symptom. This is the rule that makes an
   * eleventh unnecessary. */
  /* ---------------------------------------------------- THE PAPER LAYER
   *
   * The landing page draws Wodouh as what it is: a contract being read, with a
   * pen. This carries the same idiom into the product, so the page a reader
   * lands on and the screens they then use are one document, not two brands.
   * Five marks, used sparingly and always from the palette tokens so dark mode
   * follows for free:
   *   · a highlighter under screen titles (.hl, wrapped in markHeads())
   *   · the clause quote highlighted in its own severity colour
   *   · documents (report, letter, case file) as sheets with a second sheet
   *     showing beneath
   *   · the score drawn as a seal, with a dashed inner ring
   *   · dashed rules and index-card corners where the app used hairlines and
   *     rounded pills
   * Nothing here moves layout or changes a tap target: every mark is a
   * background, a border style or a pseudo-element. */
  :root{--hl:color-mix(in srgb,var(--amber) 26%,transparent)}
  .hl{background-image:linear-gradient(var(--hl),var(--hl));background-repeat:no-repeat;
    background-size:100% 34%;background-position:100% 88%;padding:0 3px;
    -webkit-box-decoration-break:clone;box-decoration-break:clone}
  html[dir="ltr"] .hl{background-position:0 88%}

  /* Documents are sheets: squarer corners, and a second sheet beneath. */
  .score-card,.letter{position:relative;isolation:isolate;border-radius:8px}
  /* The second sheet is drawn as a shadow, so it sits truly beneath the page
     and can never show an edge through it or push past the screen. */
  .score-card,.letter{box-shadow:var(--e2),6px 7px 0 -1px var(--card),6px 7px 0 0 var(--line)}
  html[dir="rtl"] .score-card,html[dir="rtl"] .letter{box-shadow:var(--e2),-6px 7px 0 -1px var(--card),-6px 7px 0 0 var(--line)}
  .rp-head,.letterhead{border-bottom:3px double var(--line)}
  .rp-meta,.acc-sec{border-top-style:dashed}

  /* The seal. The ring keeps its geometry; only a dashed ring is drawn round it. */
  .score-card .ring::before{content:"";position:absolute;inset:-9px;border-radius:50%;
    border:1.5px dashed color-mix(in srgb,var(--band) 55%,transparent);pointer-events:none}

  /* The quote is the reader's own clause, so it is marked the way the landing
     sheet marks one: a highlighter stroke in the finding's colour, upright,
     not an italic aside in a grey box. */
  .flag .quote,.clause .quote{background:transparent;border-inline-start:0;padding:4px 0;font-style:normal;
    color:var(--ink);line-height:2}
  .quote mark{color:inherit;background-color:transparent;background-repeat:no-repeat;
    background-image:linear-gradient(var(--qm,var(--hl)),var(--qm,var(--hl)));padding:1px 2px;border-radius:3px;
    -webkit-box-decoration-break:clone;box-decoration-break:clone}
  .flag.red,.clause.red{--qm:color-mix(in srgb,var(--red) 22%,transparent)}
  .flag.amber,.clause.amber{--qm:color-mix(in srgb,var(--amber) 24%,transparent)}
  .flag.green,.clause.green{--qm:color-mix(in srgb,var(--green) 20%,transparent)}
  .quote[data-own]{border-inline-start:0}

  /* Index cards: the doors on home and the answers in the library get a
     turned-down corner and paper corners. */
  .sit-card,.lib-item,.pcard{border-radius:8px;position:relative}
  .sit-card::after{content:"";position:absolute;top:-1px;inset-inline-end:-1px;width:18px;height:18px;
    border-start-end-radius:8px;pointer-events:none;
    background:linear-gradient(225deg,var(--sand) 50%,color-mix(in srgb,var(--line) 55%,var(--card)) 50%)}
  html[dir="rtl"] .sit-card::after{background:linear-gradient(135deg,var(--sand) 50%,color-mix(in srgb,var(--line) 55%,var(--card)) 50%)}
  .lib-a{border-top:1px dashed var(--line);padding-top:12px}

  /* Plans read as tickets: a perforation between the price and what you get,
     and the recommended tag stamped rather than printed. */
  .pcard ul{border-top:1.5px dashed var(--line);padding-top:14px}
  .pcard .tag{transform:rotate(-3deg);border:1.5px solid currentColor}
  html[dir="ltr"] .pcard .tag{transform:rotate(3deg)}

  /* The upload card on home is pinned to the page with a strip of tape. */
  .hm-up{position:relative;border-radius:8px}
  .hm-up::before{content:"";position:absolute;top:-8px;left:50%;width:64px;height:18px;margin-left:-32px;
    background:color-mix(in srgb,var(--amber-bg) 80%,transparent);border:1px solid color-mix(in srgb,var(--line) 60%,transparent);
    transform:rotate(-2deg);pointer-events:none}

  /* Letters are written on ruled paper, and end on a line for the signature. */
  .letter .body{background-image:linear-gradient(to bottom,transparent calc(1lh - 1px),
    color-mix(in srgb,var(--line) 36%,transparent) calc(1lh - 1px));background-size:100% 1lh;background-repeat:repeat-y}
  @media print{ .letter .body{background:none} .score-card,.letter{box-shadow:none} }
  .letter .sign-line{justify-content:flex-start;margin-top:26px}
  .letter .sign-line span{flex:none}

  /* Findings are numbered the way a contract numbers its clauses. */
  .flags{counter-reset:clause}
  .flag h4::before{counter-increment:clause;content:counter(clause);
    font-family:var(--en);font-weight:800;font-size:12px;color:var(--ink-2);margin-inline-end:8px;
    display:inline-block;min-width:20px;padding:0 5px;line-height:18px;text-align:center;vertical-align:2px;
    border:1px solid color-mix(in srgb,var(--ink-2) 45%,transparent);border-radius:4px}

  /* The decision reads as a stamp: a dashed double edge in its own colour,
     set a degree off true the way a hand-pressed stamp lands. */
  .decision{border:2px dashed color-mix(in srgb,var(--dc) 55%,transparent);border-radius:10px;
    outline:1px solid color-mix(in srgb,var(--dc) 22%,transparent);outline-offset:3px;transform:rotate(-.6deg)}
  html[dir="ltr"] .decision{transform:rotate(.6deg)}

  /* Sub-headings are kickers with a short pen rule, as on the landing page. */
  .biz-h{display:flex;align-items:center;gap:10px}
  .biz-h::after{content:"";flex:1;max-width:90px;border-top:1.5px dashed var(--line)}

  /* The report is signed at its foot. */
  .rp-signed{margin-top:22px}
  .rp-signed .by{min-width:150px}

  /* Home's headline: the answer half in teal, a signature drawn beneath it. */
  .hm-accent{color:var(--teal)}
  .hm-sig{display:block;color:var(--teal);margin-top:2px}
  .hm-sig .sig{display:block;width:min(220px,60%);height:28px;overflow:visible}
  html[dir="rtl"] .hm-sig .sig{transform:scaleX(-1);margin-inline-start:0}
  .hm-sig path{fill:none;stroke:currentColor;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round;
    stroke-dasharray:640;stroke-dashoffset:640;animation:sign 1.6s .4s cubic-bezier(.45,.05,.25,1) forwards}
  @keyframes sign{to{stroke-dashoffset:0}}
  @media (prefers-reduced-motion:reduce){ .hm-sig path{animation:none;stroke-dashoffset:0} }

  /* Signature blocks: where Wodouh stands behind a page, it signs it. */
  .signed-by{display:flex;flex-direction:column;align-items:flex-end;margin-top:18px;color:var(--teal)}
  .signed-by svg.sig{width:150px;height:30px;overflow:visible}
  .signed-by svg.sig path{fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
  html[dir="rtl"] .signed-by svg.sig{transform:scaleX(-1)}
  .signed-by .by{min-width:170px;border-top:1.5px dashed var(--ink-2);padding-top:6px;text-align:center;
    font-size:12px;color:var(--ink-2)}
  .sign-line{display:flex;align-items:center;gap:10px;margin:18px 0 0;color:var(--ink-2);font-size:12px}
  .sign-line::after{content:"";flex:1;border-top:1.5px dashed var(--ink-2);max-width:220px}

  /* ------------------------------------------- THE PAPER LAYER, EVERYWHERE
   *
   * The first pass dressed the screens a reader shows to someone else (the
   * report, the letter, the plans). Every other screen kept the soft app
   * card, so the product read as two designs. This makes paper the default:
   * squarer corners across every card, control and field; sheets beneath the
   * figures a reader came for; clause-numbered kickers; stamped badges; ruled
   * writing surfaces; dashed perforations where a hairline used to divide.
   * Still tokens only, still no layout or tap-target change. */
  :root,:root[data-theme="dark"],:root[data-theme="light"]{
    --r-sm:6px; --r-md:8px; --r-lg:8px; --r-xl:10px; --r-2xl:10px}

  /* The figures a reader came for are sheets, with a second sheet beneath. */
  .eos-card,.tm-hero,.tm-money,.triage,.claim-card{position:relative;isolation:isolate}
  .eos-card,.tm-hero{box-shadow:var(--e1),5px 6px 0 -1px var(--card),5px 6px 0 0 var(--line)}
  html[dir="rtl"] .eos-card,html[dir="rtl"] .tm-hero{box-shadow:var(--e1),-5px 6px 0 -1px var(--card),-5px 6px 0 0 var(--line)}
  .eos-card .svc,.tm-money .r{border-bottom-style:dashed}
  .tm-hero .alt{border-top-style:dashed}
  .tm-money .r.tot{border-top-style:double;border-top-width:3px}
  .rows .r.tot{border-top:3px double var(--line)}

  /* Index-card corners on every card a reader picks or files. */
  .sample,.src,.tl-card,.fu-card,.fu-cat,.doc,.claim-card,.brow,.up-main{position:relative}
  .sample::after,.src::after,.tl-card::after,.fu-card::after,.fu-cat::after,.doc::after,.claim-card::after,.brow::after{
    content:"";position:absolute;top:-1px;inset-inline-end:-1px;width:16px;height:16px;pointer-events:none;
    border-start-end-radius:var(--r-md);
    background:linear-gradient(225deg,var(--sand) 50%,color-mix(in srgb,var(--line) 55%,var(--card)) 50%)}
  html[dir="rtl"] :is(.sample,.src,.tl-card,.fu-card,.fu-cat,.doc,.claim-card,.brow)::after{
    background:linear-gradient(135deg,var(--sand) 50%,color-mix(in srgb,var(--line) 55%,var(--card)) 50%)}

  /* The upload card is taped down here too. */
  .up-main::before{content:"";position:absolute;top:-8px;left:50%;width:56px;height:16px;margin-left:-28px;
    background:color-mix(in srgb,var(--amber-bg) 80%,transparent);border:1px solid color-mix(in srgb,var(--line) 60%,transparent);
    transform:rotate(2deg);pointer-events:none}

  /* Writing surfaces are ruled, aligned to their own line height. */
  textarea{line-height:1.9;background-image:linear-gradient(to bottom,transparent calc(1lh - 1px),
    color-mix(in srgb,var(--line) 34%,transparent) calc(1lh - 1px));background-size:100% 1lh;
    background-attachment:local;background-position:0 14px}

  /* Group headings read as clause kickers: «البند 2 · وأنت على رأس العمل». */
  .lib-list,#libList,.screen{counter-reset:kick}
  .lib-g{counter-increment:kick}
  .lib-g::before{content:"البند " counter(kick) " ·";width:auto;height:auto;border-radius:0;background:none;
    font-weight:400;color:var(--teal)}
  html[lang="en"] .lib-g::before{content:"Clause " counter(kick) " ·"}
  .lib-g{border-top-style:dashed}
  .fu-h{display:flex;align-items:center;gap:10px}
  .fu-h::after{content:"";flex:1;max-width:90px;border-top:1.5px dashed var(--line)}
  .fu-step + .fu-step{border-top-style:dashed}

  /* Badges are stamped rather than printed. */
  .fu-card .badge,.fu-cat .badge,.fu-step .badge,.plan .badge,.up-photo .badge{
    border:1.5px dashed currentColor;transform:rotate(-3deg);border-radius:4px}
  html[dir="ltr"] :is(.fu-card,.fu-cat,.fu-step,.plan,.up-photo) .badge{transform:rotate(3deg)}

  /* Onboarding: the illustration sits on a ruled sheet, not a halo. */
  .ob-art::before{inset:-4% 2%;border-radius:6px;background:var(--card);border:1px solid var(--line);
    transform:rotate(-4deg);box-shadow:var(--e1);
    background-image:linear-gradient(to bottom,transparent 21px,color-mix(in srgb,var(--line) 34%,transparent) 21px 22px);
    background-size:100% 22px}
  html[dir="ltr"] .ob-art::before{transform:rotate(4deg)}

  /* ---------------------------------------------------- READING, SHOWN
   * The loading screen was a grey skeleton of a result. It is now the thing
   * actually happening: a contract on a ruled sheet, a highlighter passing
   * down its lines one after another, the score's seal waiting at the top. */
  .skel{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:22px 20px 20px;gap:12px;
    box-shadow:var(--e1),-5px 6px 0 -1px var(--card),-5px 6px 0 0 var(--line)}
  html[dir="ltr"] .skel{box-shadow:var(--e1),5px 6px 0 -1px var(--card),5px 6px 0 0 var(--line)}
  .skel-ring{width:64px;height:64px;border-width:3px;border-style:dashed;opacity:.7;margin-bottom:4px}
  .sk{height:9px !important;border-radius:2px;background:color-mix(in srgb,var(--ink-2) 22%,transparent);opacity:1;
    margin:0 !important;justify-self:start}
  .sk.l1{width:88%} .sk.l2{width:64%} .sk.row{width:94%} .sk.row + .sk.row{width:76%} .sk.row + .sk.row + .sk.row{width:84%}
  .sk::after{inset:-4px -2px;border-radius:3px;transform:scaleX(0);transform-origin:right;
    background:color-mix(in srgb,var(--amber) 30%,transparent);animation:hl-pass 3.2s var(--ease-out) infinite}
  html[dir="ltr"] .sk::after{transform-origin:left}
  .sk.l2::after{animation-delay:.35s} .sk.row::after{animation-delay:.7s}
  .sk.row + .sk.row::after{animation-delay:1.05s} .sk.row + .sk.row + .sk.row::after{animation-delay:1.4s}
  @keyframes hl-pass{0%{transform:scaleX(0)} 35%,80%{transform:scaleX(1)} 100%{transform:scaleX(1);opacity:0}}

  /* The tab you are on is marked the way a reader marks a page: a stroke of
     highlighter under its name. */
  .tab.on span{background-image:linear-gradient(var(--hl),var(--hl));background-repeat:no-repeat;
    background-size:100% 40%;background-position:0 90%;padding:0 2px}

  [hidden]{display:none !important}
