/* ============================================================================
   KADIA — visual direction: "الفحص / הבדיקה" (The Inspection)

   THESIS      The annual vehicle-test printout every Israeli driver already
               knows: a list of checkpoints, a finding beside each one, one
               plain verdict on top. The interface stops promising and starts
               showing. Refuses the legal-tech default of a friendly gradient
               over three identical feature cards.
   OWN-WORLD   Instrument paper (#f3f5f1) and ink (#13171a); one hairline
               weight everywhere; the checkpoint row as the atom; findings in
               signal green, uncertainty in amber. No shadow-as-decoration,
               no glass, no gradient, no pill. Rubik alone, Arabic and Hebrew
               on one skeleton, digits always tabular.
   STORY       A driver holding a ticket in a language they half-read learns,
               within seconds and for free, that this thing gets checked
               against something real — and watches it happen.
   FIRST VIEWPORT
               Headline and free-check promise at top; below it a live
               inspection report whose rows resolve one at a time, each with
               its legal source; the verdict sits on an ink bar at the card's
               foot; the primary action pins to the bottom of the phone.
   FORM        Direction 01 of three presented; user selected it 2026-08-21.
               Derived manually — the skill's concept-seed script needs
               Node.js, which this machine does not have.
   FINISH      unreviewed and undocumented is unfinished; this build ends
               with the finish review, the verdict, DESIGN.md, and every
               shipping raster carrying its provenance.
   ============================================================================ */

/* Rubik is the only family on Google Fonts that ships real Arabic, Hebrew and
   Latin subsets on one skeleton — verified by measurement, not by the CSS.
   That matters here because the two languages are shown separately: switch to
   Hebrew and you get a fully Hebrew screen with nowhere for a fallback font to
   hide. The previous Cairo/Tajawal pair declared no Hebrew range at all, so
   every Hebrew character on the site rendered in the device default.
   Self-hosted rather than CDN-linked, deliberately: one less third party in
   the critical path, and it works in environments that block the CDN. */
@font-face {
  font-family: 'Rubik';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/assets/fonts/rubik-arabic.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
                 U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41,
                 U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Rubik';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/assets/fonts/rubik-hebrew.woff2') format('woff2');
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
@font-face {
  font-family: 'Rubik';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/assets/fonts/rubik-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ---- the world, named for what it is ---- */
  --paper:        #f3f5f1;   /* the ground: instrument paper, faintly cool */
  --paper-dim:    #e9ece7;   /* recessed bands, table zebra */
  --plate:        #ffffff;   /* the report itself sits on white */
  --ink:          #13171a;   /* headings, verdict bars, primary text */
  --ink-2:        #4d5651;   /* body text on paper */
  --ink-3:        #6a716c;   /* captions, fine print — AA on paper */
  --rule:         #d7dcd7;   /* the one hairline weight */
  --rule-strong:  #13171a;   /* a report's own border is full ink */
  --on-ink:       #e2e6e2;   /* body text on an ink surface */
  --on-ink-dim:   #a6aea8;   /* secondary text on ink — still AA */
  --rule-on-ink:  #2c3438;   /* the hairline, on ink */

  --signal:       #0f7a45;   /* a finding: a real ground for appeal */
  --signal-bright:#22c07a;   /* same signal, for ink-dark surfaces only */
  --signal-tint:  #e7f2ec;
  --caution:      #b4531a;   /* we could not read this / check it yourself */
  --caution-tint: #fbf1e9;
  --stop:         #b3261e;   /* money you lose, deadlines you miss */
  --stop-tint:    #fdeeec;

  /* ---- type: one family, fixed scale, Operate-tight ratio ---- */
  --font: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --t-xs:   0.75rem;    /* 12 — uppercase labels only */
  --t-sm:   0.8125rem;  /* 13 — captions, table cells */
  --t-md:   0.9375rem;  /* 15 — secondary body */
  --t-base: 1rem;       /* 16 — body, never smaller for reading text */
  --t-lg:   1.125rem;   /* 18 — lead paragraphs */
  --t-xl:   1.375rem;   /* 22 — h3 */
  --t-2xl:  1.75rem;    /* 28 — h2 */
  --t-3xl:  2.25rem;    /* 36 — page titles */
  --t-4xl:  3rem;       /* 48 — hero, desktop only */

  /* ---- geometry: sharp plates, comfortable controls ---- */
  --r-plate: 4px;       /* anything that reads as a document */
  --r-ctl:   12px;      /* anything a thumb presses */
  --r-field: 10px;
  --radius:  4px;       /* legacy alias, see below */
  /* two more content-card tiers already existed as repeated literals
     (option pills, promo banners, ground results, upload preview) before
     they had names - naming them here doesn't change a single pixel, it
     just makes the relationship explicit for the next person editing them. */
  --r-card:    16px;
  --r-card-sm: 14px;

  /* depth is offset + blur, never a coloured halo */
  --shadow:    0 1px 2px rgba(19, 23, 26, .06);
  --shadow-lg: 0 2px 4px rgba(19, 23, 26, .07), 0 18px 36px -14px rgba(19, 23, 26, .22);

  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur:  .18s;

  /* ---- legacy aliases ----------------------------------------------------
     400+ existing declarations reference these names. Repointing them here
     moves the whole site into the new world in one place instead of touching
     every rule, and keeps admin.html (which shares this stylesheet but is out
     of design scope) working untouched. New rules should use the names above. */
  --kadia-navy:         var(--ink);
  --kadia-teal:         var(--signal);
  --kadia-teal-dark:    #0b5f36;
  --kadia-teal-deep:    #084a2a;
  --kadia-teal-light:   var(--signal-bright);
  --kadia-teal-tint:    var(--signal-tint);
  --kadia-gold:         var(--caution);
  --kadia-gold-light:   #d98a4e;
  --kadia-gold-text:    #8f3f11;
  --kadia-bg:           var(--paper);
  --kadia-bg-dim:       var(--paper-dim);
  --kadia-card:         var(--plate);
  --kadia-text:         var(--ink);
  --kadia-text-muted:   var(--ink-3);
  --kadia-border:       var(--rule);
  --kadia-success:      var(--signal);
  --kadia-success-tint: var(--signal-tint);
  --kadia-danger:       var(--stop);

  /* ---- violation-type category colors ----------------------------------
     Eight distinct, solid, high-saturation hues, one per seeded violation
     type - shared between the small icon tile (chip/pill) and the bigger
     mobile category card. See the ".chip[data-value] .chip-ico" block
     further down for the reasoning (real-world association where one
     exists, kept distinct rather than a tighter palette for fast category
     recognition in a picker). */
  --cat-parking:              #2563eb;
  --cat-red_white:            #dc2626;
  --cat-lpr_camera:           #7c3aed;
  --cat-public_transit_lane:  #ea580c;
  --cat-officer:              #4338ca;
  --cat-scooter:              #0d9488;
  --cat-airport:              #0891b2;
  --cat-other:                #64748b;
}

* { box-sizing: border-box; }

/* Controls do not inherit font-family by default; on a page whose whole
   argument is that both its languages are properly typeset, a button in the
   system font is exactly the tell we are removing. */
button, input, select, textarea { font-family: inherit; font-size: inherit; }

html, body {
  margin: 0;
  padding: 0;
  direction: rtl;
  text-align: right;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.62;
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Arabic and Hebrew are both RTL, so `dir` never flips — only `lang` does.
   Hebrew sits slightly smaller on the same body size than Arabic, so it gets
   a touch more line-height to keep the two languages optically equal. */
html[lang="he"] body { line-height: 1.66; }

h1, h2, h3, h4, h5 {
  margin: 0;
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -.015em;
  text-wrap: balance;
  color: var(--ink);
}
h1 { font-size: var(--t-3xl); }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-xl); }
h4 { font-size: var(--t-lg); }
p  { margin: 0; }

a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; margin: 0; padding: 0; }
img { max-width: 100%; display: block; }
strong, b { font-weight: 700; }

/* Numbers are measurements in this world — ticket numbers, amounts, dates,
   deadlines — so they line up in columns and never reflow with the RTL text
   around them. */
.num, input[type="tel"], input[type="number"],
td.num, .price-tag, .amt {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.num { direction: ltr; unicode-bidi: isolate; display: inline-block; }

/* The browser surfaces we did not draw still carry the design. */
::selection { background: var(--signal); color: #fff; }
:root { accent-color: var(--signal); caret-color: var(--signal); }
:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
  border-radius: 2px;
}
* { scrollbar-width: thin; scrollbar-color: #b9c0ba transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: #b9c0ba; border-radius: 10px; border: 2px solid var(--paper); }
*::-webkit-scrollbar-thumb:hover { background: #98a09a; }

.container {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 20px;
}

/* A small caps-label used across the report surfaces. */
.mk-label, .section-kicker {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--ink-3);
  text-transform: uppercase;
}


/* ============================================================================
   Icon system
   ----------------------------------------------------------------------------
   Replaces the emoji that stood in for icons (⏱ ⚖️ 🧾 🎁 🔒 …). Emoji render
   differently on every device, ignore the brand palette entirely, and read as
   placeholder. These are drawn on one 24px grid at one stroke weight (1.8),
   round caps and joins, and they take their colour from `currentColor`.

   Delivered as CSS mask-images rather than an SVG sprite because the header and
   footer are duplicated across nine static pages with no build step and no
   templating: a sprite would have to be pasted nine times and kept in sync.
   A mask lives in one file, needs no JS, and still inherits colour.

   Usage:  <span class="ico ico-check" aria-hidden="true"></span>
   Size:   font-size on the element, or .ico-lg / .ico-sm
   ============================================================================ */
.ico {
  display: inline-block;
  width: 1em;
  height: 1em;
  flex: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  vertical-align: -0.14em;
}
.ico-sm { font-size: .875rem; }
.ico-lg { font-size: 1.5rem; }
.ico-xl { font-size: 2rem; }

/* A check inside a ring: the report's "this is a finding" mark. */
.ico-check-ring { -webkit-mask-image: var(--i-check-ring); mask-image: var(--i-check-ring); }
.ico-check      { -webkit-mask-image: var(--i-check);      mask-image: var(--i-check); }
.ico-alert      { -webkit-mask-image: var(--i-alert);      mask-image: var(--i-alert); }
.ico-clock      { -webkit-mask-image: var(--i-clock);      mask-image: var(--i-clock); }
.ico-scale      { -webkit-mask-image: var(--i-scale);      mask-image: var(--i-scale); }
.ico-doc        { -webkit-mask-image: var(--i-doc);        mask-image: var(--i-doc); }
.ico-lock       { -webkit-mask-image: var(--i-lock);       mask-image: var(--i-lock); }
.ico-camera     { -webkit-mask-image: var(--i-camera);     mask-image: var(--i-camera); }
.ico-user       { -webkit-mask-image: var(--i-user);       mask-image: var(--i-user); }
.ico-home       { -webkit-mask-image: var(--i-home);       mask-image: var(--i-home); }
.ico-gift       { -webkit-mask-image: var(--i-gift);       mask-image: var(--i-gift); }
.ico-shield     { -webkit-mask-image: var(--i-shield);     mask-image: var(--i-shield); }
.ico-arrow      { -webkit-mask-image: var(--i-arrow);      mask-image: var(--i-arrow); }
.ico-pin        { -webkit-mask-image: var(--i-pin);        mask-image: var(--i-pin); }
.ico-refresh    { -webkit-mask-image: var(--i-refresh);    mask-image: var(--i-refresh); }
.ico-clip       { -webkit-mask-image: var(--i-clip);       mask-image: var(--i-clip); }
.ico-printer    { -webkit-mask-image: var(--i-printer);    mask-image: var(--i-printer); }
.ico-chat       { -webkit-mask-image: var(--i-chat);       mask-image: var(--i-chat); }
.ico-menu       { -webkit-mask-image: var(--i-menu);       mask-image: var(--i-menu); }
.ico-close      { -webkit-mask-image: var(--i-close);      mask-image: var(--i-close); }
.ico-edit       { -webkit-mask-image: var(--i-edit);       mask-image: var(--i-edit); }
.ico-id         { -webkit-mask-image: var(--i-id);         mask-image: var(--i-id); }
.ico-mail       { -webkit-mask-image: var(--i-mail);       mask-image: var(--i-mail); }
.ico-globe      { -webkit-mask-image: var(--i-globe);      mask-image: var(--i-globe); }
.ico-scan       { -webkit-mask-image: var(--i-scan);       mask-image: var(--i-scan); }
.ico-circle     { -webkit-mask-image: var(--i-circle);     mask-image: var(--i-circle); }
.ico-dash       { -webkit-mask-image: var(--i-dash);       mask-image: var(--i-dash); }

/* 2026-08-28: every "concept" icon (the ones standing in for a real idea -
   a document, a camera, a clock) switched from a currentColor mask to a
   real full-color drawing, on explicit request after the redesign trial:
   "living, colorful icons... a different color per concept, same subject."
   Pure UI chrome stays mask-based on purpose: check/check-ring (a tiny
   inline status glyph, already reads as green via context wherever it's
   used), menu/close/arrow/circle/dash (navigation controls that have to
   sit on whatever background/color surrounds them, not carry their own
   fixed palette - a rainbow hamburger icon or a green X on a red error
   banner would read as broken, not "colorful"). Each override only swaps
   the paint method (mask -> background-image); .ico's shared sizing,
   display and vertical-align rules still apply untouched. */
.ico-alert, .ico-clock, .ico-scale, .ico-doc, .ico-lock, .ico-camera,
.ico-user, .ico-home, .ico-gift, .ico-shield, .ico-pin, .ico-refresh,
.ico-clip, .ico-printer, .ico-chat, .ico-edit, .ico-id, .ico-mail,
.ico-globe, .ico-scan {
  -webkit-mask-image: none; mask-image: none;
  background-color: transparent;
  background-repeat: no-repeat; background-position: center; background-size: contain;
}
.ico-alert   { background-image: var(--i-alert-color); }
.ico-clock   { background-image: var(--i-clock-color); }
.ico-scale   { background-image: var(--i-scale-color); }
.ico-doc     { background-image: var(--i-doc-color); }
.ico-lock    { background-image: var(--i-lock-color); }
.ico-camera  { background-image: var(--i-camera-color); }
.ico-user    { background-image: var(--i-user-color); }
.ico-home    { background-image: var(--i-home-color); }
.ico-gift    { background-image: var(--i-gift-color); }
.ico-shield  { background-image: var(--i-shield-color); }
.ico-pin     { background-image: var(--i-pin-color); }
.ico-refresh { background-image: var(--i-refresh-color); }
.ico-clip    { background-image: var(--i-clip-color); }
.ico-printer { background-image: var(--i-printer-color); }
.ico-chat    { background-image: var(--i-chat-color); }
.ico-edit    { background-image: var(--i-edit-color); }
.ico-id      { background-image: var(--i-id-color); }
.ico-mail    { background-image: var(--i-mail-color); }
.ico-globe   { background-image: var(--i-globe-color); }
.ico-scan    { background-image: var(--i-scan-color); }

/* Three spots put one of the icons above on a solid --signal green fill
   (the mobile scan FAB, the promo banner's CTA button, the dashboard's
   active sidebar item) - a busy multi-tone drawing doesn't read as a clean
   button glyph there the way it does inside a white card (flagged live:
   the FAB's camera all but disappeared into the green). Reverting just
   these instances back to a plain white silhouette - color:#fff is already
   set by each of these components - keeps the full-color drawing
   everywhere else that actually has room for it. */
.bottom-tab-fab .ico-camera,
.promo-strip-cta .ico-gift,
.account-nav-item.active .ico-doc,
.account-nav-item.active .ico-user,
.account-nav-item.active .ico-lock,
.account-nav-item.active .ico-chat,
.account-nav-item.active .ico-alert {
  background-image: none;
  background-color: currentColor;
}
.bottom-tab-fab .ico-camera         { -webkit-mask-image: var(--i-camera); mask-image: var(--i-camera); }
.promo-strip-cta .ico-gift          { -webkit-mask-image: var(--i-gift);   mask-image: var(--i-gift); }
.account-nav-item.active .ico-doc   { -webkit-mask-image: var(--i-doc);    mask-image: var(--i-doc); }
.account-nav-item.active .ico-user  { -webkit-mask-image: var(--i-user);   mask-image: var(--i-user); }
.account-nav-item.active .ico-lock  { -webkit-mask-image: var(--i-lock);   mask-image: var(--i-lock); }
.account-nav-item.active .ico-chat  { -webkit-mask-image: var(--i-chat);   mask-image: var(--i-chat); }
.account-nav-item.active .ico-alert { -webkit-mask-image: var(--i-alert);  mask-image: var(--i-alert); }

/* The drawings themselves. Kept as custom properties so a single icon can be
   swapped in one place, and so the .ico-* rules above stay readable. */
:root {
  --i-check-ring: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.3l2.7 2.6L16 9.4'/%3E%3C/svg%3E");
  --i-check:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5L20 6.8'/%3E%3C/svg%3E");
  --i-alert:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.6 2.6 19.2A1.4 1.4 0 0 0 3.8 21.3h16.4a1.4 1.4 0 0 0 1.2-2.1L12 3.6Z'/%3E%3Cpath d='M12 9.6v4.2M12 17.4h.01'/%3E%3C/svg%3E");
  --i-clock:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 6.8V12l3.4 2'/%3E%3C/svg%3E");
  --i-scale:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.4v17.2M7.5 20.6h9M3 8.2h18M3 8.2l4.4-4h9.2l4.4 4'/%3E%3Cpath d='M3 8.2 1.4 13.2a3.1 3.1 0 0 0 6.2 0L6 8.2M18 8.2l-1.6 5a3.1 3.1 0 0 0 6.2 0L21 8.2'/%3E%3C/svg%3E");
  --i-doc:        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2.8H7a2 2 0 0 0-2 2v14.4a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7.8Z'/%3E%3Cpath d='M14 2.8v5h5M8.6 13h6.8M8.6 16.6h4.4'/%3E%3C/svg%3E");
  --i-lock:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4.2' y='10.4' width='15.6' height='10.6' rx='2.4'/%3E%3Cpath d='M8 10.4V7a4 4 0 0 1 8 0v3.4'/%3E%3Ccircle cx='12' cy='15.6' r='1.3'/%3E%3C/svg%3E");
  --i-camera:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.6h3.2l1.6-2.4h8.4l1.6 2.4H21a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1Z'/%3E%3Ccircle cx='12' cy='13.8' r='3.6'/%3E%3C/svg%3E");
  --i-user:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8.2' r='3.8'/%3E%3Cpath d='M4.6 20.4a7.4 7.4 0 0 1 14.8 0'/%3E%3C/svg%3E");
  --i-gift:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='9.6' width='18' height='4.2' rx='1'/%3E%3Cpath d='M4.6 13.8v6.2a1 1 0 0 0 1 1h12.8a1 1 0 0 0 1-1v-6.2M12 9.6v11.4'/%3E%3Cpath d='M12 9.6H7.9a2.45 2.45 0 1 1 0-4.9C10.8 4.7 12 9.6 12 9.6ZM12 9.6h4.1a2.45 2.45 0 1 0 0-4.9C13.2 4.7 12 9.6 12 9.6Z'/%3E%3C/svg%3E");
  --i-shield:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.8 4.4 6v5.6c0 4.6 3.2 8.9 7.6 9.9 4.4-1 7.6-5.3 7.6-9.9V6Z'/%3E%3Cpath d='M9 12.2l2.1 2 3.9-4'/%3E%3C/svg%3E");
  --i-arrow:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 12H4M10 6l-6 6 6 6'/%3E%3C/svg%3E");
  --i-pin:        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10.4c0 5.6-8 11.4-8 11.4s-8-5.8-8-11.4a8 8 0 1 1 16 0Z'/%3E%3Ccircle cx='12' cy='10.2' r='2.9'/%3E%3C/svg%3E");
  --i-refresh:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 11.2a8.5 8.5 0 1 0-.7 4.6'/%3E%3Cpath d='M20.6 5.6v5.6H15'/%3E%3C/svg%3E");
  --i-clip:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.4 11.6 12.7 19.3a5 5 0 0 1-7.1-7.1l7.8-7.7a3.3 3.3 0 1 1 4.7 4.7l-7.7 7.7a1.7 1.7 0 0 1-2.4-2.4l7.1-7.1'/%3E%3C/svg%3E");
  --i-printer:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.6 9.4V3.4h10.8v6M6.6 18.2H4.4a1.4 1.4 0 0 1-1.4-1.4v-5.6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5.6a1.4 1.4 0 0 1-1.4 1.4h-2.2'/%3E%3Crect x='6.6' y='14.6' width='10.8' height='6'/%3E%3C/svg%3E");
  --i-chat:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.6 12.2a7.8 7.8 0 0 1-8.4 7.8 9 9 0 0 1-2.5-.4L4 21.2l1.7-5.2a7.6 7.6 0 0 1-.9-3.6 7.8 7.8 0 0 1 7.8-7.6h.5a7.8 7.8 0 0 1 7.5 7.4Z'/%3E%3C/svg%3E");
  --i-menu:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h16M4 12h16M4 17h16'/%3E%3C/svg%3E");
  --i-close:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E");
  --i-edit:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.5 4.2 19.8 9.5 9.3 20H4v-5.3z'/%3E%3Cpath d='M12.8 5.9l5.3 5.3'/%3E%3C/svg%3E");
  --i-id:         url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.6' y='5' width='18.8' height='14' rx='2'/%3E%3Ccircle cx='8.4' cy='10.8' r='2.1'/%3E%3Cpath d='M5.2 15.8a3.6 3.6 0 0 1 6.4 0M14.6 10h4.2M14.6 13.6h4.2'/%3E%3C/svg%3E");
  --i-mail:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.6' y='4.8' width='18.8' height='14.4' rx='2'/%3E%3Cpath d='m3.4 6.6 8.6 6.2 8.6-6.2'/%3E%3C/svg%3E");
  --i-globe:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3 12h18M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18Z'/%3E%3C/svg%3E");
  --i-scan:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8.4V5.6A1.6 1.6 0 0 1 5.6 4h2.8M15.6 4h2.8A1.6 1.6 0 0 1 20 5.6v2.8M20 15.6v2.8a1.6 1.6 0 0 1-1.6 1.6h-2.8M8.4 20H5.6A1.6 1.6 0 0 1 4 18.4v-2.8'/%3E%3Cpath d='M4 12h16'/%3E%3C/svg%3E");
  --i-circle:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8'%3E%3Ccircle cx='12' cy='12' r='8.4'/%3E%3C/svg%3E");
  --i-dash:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-dasharray='3 2.6'%3E%3Ccircle cx='12' cy='12' r='8.4'/%3E%3C/svg%3E");
  --i-home:       url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11.4 12 4l8 7.4'/%3E%3Cpath d='M6 10v9.4h5V14h2v5.4h5V10'/%3E%3C/svg%3E");

  /* Full-color versions of the 20 "concept" icons above (see the .ico-alert
     etc. override block near the top of the icon system). Same subject and
     silhouette as their mono originals, each in its own fixed hue rather
     than currentColor - grouped loosely by meaning so the sitewide result
     reads as a coherent family, not random confetti: blue for tech/
     communication, green for documents/protection/home, amber for
     attention/editing, bronze for legal weight, purple for identity/
     account, red for location, blue-gray for plain office tools. */
  --i-alert-color:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5 22.5 21H1.5Z' fill='%23f0a030'/%3E%3Crect x='11' y='8.5' width='2' height='6' rx='1' fill='%23fff'/%3E%3Ccircle cx='12' cy='17.3' r='1.2' fill='%23fff'/%3E%3C/svg%3E");
  --i-clock-color:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='10' fill='%234a7cf0'/%3E%3Cpath d='M12 6.5V12l4 2.4' stroke='%23fff' stroke-width='2' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
  --i-scale-color:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='10' fill='%23c9a26a'/%3E%3Ccircle cx='12' cy='12' r='7.6' fill='%23e8cfa0'/%3E%3Cg stroke='%237a5228' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round' fill='none'%3E%3Cpath d='M12 7v9M9 18h6M6 9h12M6 9l1.7-2h8.6L18 9'/%3E%3Cpath d='M6 9l-1 2.4a1.6 1.6 0 0 0 3.2 0L7 9M18 9l-1 2.4a1.6 1.6 0 0 0 3.2 0L19 9'/%3E%3C/g%3E%3C/svg%3E");
  --i-doc-color:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.5 2h7l4 4v14a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z' fill='%233fa876'/%3E%3Cpath d='M13.5 2v4h4Z' fill='%238fd4b3'/%3E%3Crect x='8.2' y='11' width='7.6' height='1.4' rx='.7' fill='%23fff'/%3E%3Crect x='8.2' y='14.2' width='7.6' height='1.4' rx='.7' fill='%23fff'/%3E%3C/svg%3E");
  --i-lock-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='4.5' y='10.5' width='15' height='11' rx='2.4' fill='%235b52c9'/%3E%3Cpath d='M8 10.5V7a4 4 0 0 1 8 0v3.5' stroke='%235b52c9' stroke-width='2' fill='none'/%3E%3Ccircle cx='12' cy='16' r='1.6' fill='%23fff'/%3E%3C/svg%3E");
  --i-camera-color:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 8.6h3.2l1.6-2.4h8.4l1.6 2.4H21a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1Z' fill='%235b7fb8'/%3E%3Crect x='16' y='5.6' width='3.4' height='2.4' rx='.7' fill='%233f5f92'/%3E%3Ccircle cx='12' cy='13.8' r='4.4' fill='%23e8edf5'/%3E%3Ccircle cx='12' cy='13.8' r='2.6' fill='%233f5f92'/%3E%3C/svg%3E");
  --i-user-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='8.2' r='3.8' fill='%238b6fd6'/%3E%3Cpath d='M4.6 20.4a7.4 7.4 0 0 1 14.8 0Z' fill='%23a68ee0'/%3E%3C/svg%3E");
  --i-home-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 11.4 12 4l8 7.4V21a1 1 0 0 1-1 1h-4v-6.4h-6V22H5a1 1 0 0 1-1-1Z' fill='%230f7a45'/%3E%3Cpath d='M4 11.4 12 4l8 7.4' stroke='%230b5f36' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-gift-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='9.6' width='18' height='4.2' rx='1' fill='%233fa876'/%3E%3Crect x='4.6' y='13.8' width='14.8' height='7.6' rx='1' fill='%238fd4b3'/%3E%3Crect x='11' y='9.6' width='2' height='11.8' fill='%233fa876'/%3E%3Cpath d='M12 9.6H7.9a2.45 2.45 0 1 1 0-4.9C10.8 4.7 12 9.6 12 9.6ZM12 9.6h4.1a2.45 2.45 0 1 0 0-4.9C13.2 4.7 12 9.6 12 9.6Z' fill='%23f5c451'/%3E%3C/svg%3E");
  --i-shield-color:  url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.8 4.4 6v5.6c0 4.6 3.2 8.9 7.6 9.9 4.4-1 7.6-5.3 7.6-9.9V6Z' fill='%233fa876'/%3E%3Cpath d='M9 12.2l2.1 2 3.9-4' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
  --i-pin-color:     url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 10.4c0 5.6-8 11.4-8 11.4s-8-5.8-8-11.4a8 8 0 1 1 16 0Z' fill='%23e15a4a'/%3E%3Ccircle cx='12' cy='10.2' r='3.2' fill='%23fff'/%3E%3C/svg%3E");
  --i-refresh-color: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.4 11.2a8.5 8.5 0 1 0-.7 4.6' stroke='%234a7cf0' stroke-width='2.4' stroke-linecap='round' fill='none'/%3E%3Cpath d='M20.6 5.6v5.6H15' stroke='%234a7cf0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
  --i-clip-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.4 11.6 12.7 19.3a5 5 0 0 1-7.1-7.1l7.8-7.7a3.3 3.3 0 1 1 4.7 4.7l-7.7 7.7a1.7 1.7 0 0 1-2.4-2.4l7.1-7.1' stroke='%236a8caf' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
  --i-printer-color: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='5' y='9' width='14' height='7' rx='1.5' fill='%236a8caf'/%3E%3Crect x='6.6' y='3.4' width='10.8' height='6' fill='%238fabc9'/%3E%3Crect x='6.6' y='14.6' width='10.8' height='6' fill='%23fff' stroke='%236a8caf' stroke-width='1.4'/%3E%3C/svg%3E");
  --i-chat-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 8h9a2.5 2.5 0 0 1 2.5 2.5v5a2.5 2.5 0 0 1-2.5 2.5h-1v3l-3.75-3H11a2.5 2.5 0 0 1-2.5-2.5v-5A2.5 2.5 0 0 1 11 8Z' fill='%234a7cf0'/%3E%3Cpath d='M4 4h10a2.5 2.5 0 0 1 2.5 2.5v4.5a2.5 2.5 0 0 1-2.5 2.5H9l-3.5 2.75V13.5H4A2.5 2.5 0 0 1 1.5 11V6.5A2.5 2.5 0 0 1 4 4Z' fill='%23f5c451'/%3E%3C/svg%3E");
  --i-edit-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.5 4.2 19.8 9.5 9.3 20H4v-5.3z' fill='%23f0a030'/%3E%3Cpath d='M12.8 5.9l5.3 5.3' stroke='%23c97f1a' stroke-width='1.6'/%3E%3C/svg%3E");
  --i-id-color:      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='2.6' y='5' width='18.8' height='14' rx='2' fill='%238b6fd6'/%3E%3Ccircle cx='8.4' cy='10.8' r='2.1' fill='%23fff'/%3E%3Cpath d='M5.2 15.8a3.6 3.6 0 0 1 6.4 0Z' fill='%23fff'/%3E%3Crect x='14.6' y='9.2' width='4.2' height='1.6' rx='.8' fill='%23fff'/%3E%3Crect x='14.6' y='12.6' width='4.2' height='1.6' rx='.8' fill='%23fff'/%3E%3C/svg%3E");
  --i-mail-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='2.6' y='4.8' width='18.8' height='14.4' rx='2' fill='%234a7cf0'/%3E%3Cpath d='m3.4 6.6 8.6 6.2 8.6-6.2' stroke='%23e8edf5' stroke-width='1.6' fill='none'/%3E%3C/svg%3E");
  --i-globe-color:   url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='9' fill='%234a7cf0'/%3E%3Cg stroke='%23cfe0ff' stroke-width='1' fill='none'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3 12h18M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18Z'/%3E%3C/g%3E%3C/svg%3E");
  --i-scan-color:    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%234a7cf0' stroke-width='2.6' stroke-linecap='round' fill='none'%3E%3Cpath d='M4 8.4V5.6A1.6 1.6 0 0 1 5.6 4h2.8M15.6 4h2.8A1.6 1.6 0 0 1 20 5.6v2.8M20 15.6v2.8a1.6 1.6 0 0 1-1.6 1.6h-2.8M8.4 20H5.6A1.6 1.6 0 0 1 4 18.4v-2.8'/%3E%3C/g%3E%3Cellipse cx='12' cy='12' rx='5.5' ry='3.5' fill='%234a7cf0'/%3E%3Ccircle cx='12' cy='12' r='1.7' fill='%23fff'/%3E%3C/svg%3E");
}

/* The RTL "continue" arrow points toward the reading direction (left). If a
   future LTR surface is ever added, this flips it rather than shipping an
   arrow pointing backwards. */
html[dir="ltr"] .ico-arrow { transform: scaleX(-1); }

/* ---------- Scroll progress rail ---------- */
/* Reads as a measuring edge rather than a decorative gradient. */
.scroll-rail {
  position: fixed;
  top: 0;
  left: 0;
  width: 3px;
  height: 100vh;
  background: var(--rule);
  z-index: 200;
}
.scroll-rail .thumb {
  width: 100%;
  height: 0;
  background: var(--signal);
}

/* ---------- Header ---------- */
/* required by WCAG 2.4.1 / IS 5568 - lets a keyboard user jump straight past
   the header/nav on every page instead of tabbing through it every time.
   Visually hidden until it receives focus (Tab from the very top of the
   page); inset-inline-start (not "left") so it still works correctly in
   this RTL-only site if a future LTR page is ever added. */
.skip-link {
  position: absolute;
  inset-inline-start: -9999px;
  top: 12px;
  z-index: 2000;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 20px;
  border-radius: var(--r-ctl);
  font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { inset-inline-start: 12px; }

header.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  transition: border-color var(--dur) var(--ease);
}
header.site-header.scrolled { border-bottom-color: var(--ink); }

.site-header .bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 13px;
  padding-bottom: 13px;
}

/* groups the logo with the language switch so the switch reads as part of
   the brand corner of the header, at the opposite end from the CTA/login
   buttons in .nav-actions rather than crowded in among them */
.brand-row { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }

/* Mobile web-app convention: logo at the visual start (left), everything
   else - the language switch, and on pages that have one, a secondary
   nav-actions link - grouped at the visual end (right). .brand-row exists
   only to keep the logo and language switch adjacent in the normal
   (desktop) flex flow; dissolving it here lets .brand and #langToggle
   become independently orderable flex children of .bar, same as
   .nav-actions, on every page that uses this header. (A first attempt used
   flex-direction:row-reverse on .brand-row instead - that only swaps the
   two elements relative to EACH OTHER, not relative to the rest of the
   header, so on a page with no other header content, as on auth.html, the
   pair stayed bunched together at one end instead of spanning the row.) */
@media (max-width: 920px) {
  .brand-row { display: contents; }
  #langToggle { order: 1; }
  .nav-actions { order: 2; }
  .brand { order: 3; }
}

/* The wordmark: the drawn K stands in for the letter itself, with "ADIA"
   continuing directly off it — one word, not an icon beside a repeated "K".
   `direction: ltr` is required, not just the text's own isolation: on an RTL
   page a flex row's first DOM child (the icon) sits at the logical start,
   which is the visual RIGHT in RTL — so without this the icon rendered after
   "KADIA" instead of before "ADIA". Forcing the whole lockup to ltr makes the
   icon lead on the left, exactly like the mark leading a real wordmark. */
.brand {
  display: flex;
  flex-direction: row;
  direction: ltr;
  align-items: center;
  gap: 1px;
  color: var(--ink);
  flex-shrink: 0;
  line-height: 1;
}
.brand .dot { color: var(--signal); }
.brand-text {
  white-space: nowrap;
  direction: ltr;
  unicode-bidi: isolate;
  font-family: var(--font);
  font-weight: 700;
  font-style: normal;
  font-size: 1.3rem;
  letter-spacing: .01em;
  margin-inline-start: -1px;
}
.brand-icon { width: 34px; height: 34px; flex-shrink: 0; }

.nav-links {
  display: flex;
  gap: 26px;
  font-weight: 500;
  font-size: var(--t-md);
  color: var(--ink-2);
  white-space: nowrap;
}
.nav-links a { padding: 2px 0; border-bottom: 1.5px solid transparent; transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease); }
.nav-links a:hover { color: var(--ink); border-bottom-color: var(--signal); }

.nav-actions { display: flex; gap: 10px; align-items: center; flex-shrink: 0; }

.nav-hamburger {
  display: none;
  align-items: center; justify-content: center;
  background: none; border: 1px solid var(--rule); border-radius: 8px;
  line-height: 1; padding: 7px 12px; cursor: pointer;
  color: var(--ink); flex-shrink: 0; min-height: 44px; min-width: 44px;
}
/* The glyph is drawn here rather than written into the button by script:
   assigning markup to textContent printed it literally, and building it in a
   double-quoted string broke the script outright. */
.nav-hamburger::before {
  content: "";
  width: 22px; height: 22px;
  background-color: currentColor;
  -webkit-mask: var(--i-menu) center / contain no-repeat;
          mask: var(--i-menu) center / contain no-repeat;
}
.nav-hamburger.is-open::before {
  -webkit-mask-image: var(--i-close);
          mask-image: var(--i-close);
}

@media (max-width: 920px) {
  .nav-links {
    display: none;
    position: absolute; top: 100%; inset-inline: 0;
    flex-direction: column; gap: 0;
    background: var(--plate); border-bottom: 1px solid var(--ink);
    padding: 4px 20px 12px;
  }
  .nav-links a { padding: 13px 0; border-top: 1px solid var(--rule); border-bottom: 0; }
  .nav-links.mobile-open { display: flex; }
  .nav-hamburger { display: inline-flex; }
  .site-header .bar { position: relative; }
  /* .nav-actions had flex-shrink:0, so it never actually shrank to the
     point where its own flex-wrap could kick in - the two header buttons
     (login + primary CTA) just overflowed the viewport on any phone
     narrower than ~513px instead of wrapping to a second line. Still needed
     on pages without a hamburger (dashboard), where .nav-actions stays put. */
  .nav-actions { flex-shrink: 1; min-width: 0; flex-wrap: wrap; justify-content: flex-end; }
  /* the header's own "check now" CTA is redundant on mobile - the hero
     section (index.html) or the page itself (dashboard) already repeats the
     same action, so dropping the header copy declutters an already-tight
     mobile header. */
  .nav-actions .nav-check-cta { display: none; }
  /* A web-app header reads as fixed slots, not a shrinking row of buttons:
     logo at the visual start, language switch next to it, the menu trigger
     at the visual end - one order lower than #langToggle's (see the general
     .brand-row rule above) so it lands to its right. index.html is the only
     page with a hamburger/dropdown for the login/vault link and "check now"
     CTA to move into (.nav-link-mobile-auth below), so .nav-actions is
     dropped entirely here rather than kept as a fourth slot. */
  .site-header .bar:has(.nav-hamburger) .nav-hamburger { order: 0; }
  .site-header .bar:has(.nav-hamburger) .nav-actions { display: none; }
}

/* Whenever the hamburger is the way into the site's other links (≤920px),
   the login/vault link travels with them here instead of sitting in the
   header row - kept in sync with the signed-in state by kadiaRenderAuthNav()
   (api.js), which is why this has its own id rather than a static href. */
.nav-link-mobile-auth { display: none; }
@media (max-width: 920px) {
  .nav-link-mobile-auth { display: block; }
}

@media (max-width: 480px) {
  .brand-text { font-size: 1.1rem; }
  .brand-icon { width: 30px; height: 30px; }
  .btn { padding: 11px 16px; font-size: var(--t-md); }
  .nav-actions { gap: 8px; }
}

/* ---------- Scroll reveal + hero entrance ---------- */
/* One authored entrance, exponential ease-out from an already-visible
   default. Disabled entirely under prefers-reduced-motion: reveal.js still
   adds .revealed immediately in that case, and the base .reveal rule below
   never hides anything to begin with, so there is no dependency on JS for
   the reduced-motion path. */
@media (prefers-reduced-motion: no-preference) {
  html.kadia-anim .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .55s var(--ease), transform .55s var(--ease);
  }
  html.kadia-anim .reveal.revealed { opacity: 1; transform: none; }
  .reveal-1 { transition-delay: .05s; }
  .reveal-2 { transition-delay: .12s; }
  .reveal-3 { transition-delay: .19s; }

  html.kadia-anim .hero-enter {
    opacity: 0;
    transform: translateY(11px);
    animation: heroEnter .62s var(--ease) forwards;
  }
  .hero-enter-1 { animation-delay: .04s; }
  .hero-enter-2 { animation-delay: .13s; }
  .hero-enter-3 { animation-delay: .22s; }
  .hero-enter-4 { animation-delay: .31s; }
  @keyframes heroEnter { to { opacity: 1; transform: none; } }
}

/* ---------- Buttons ---------- */
/* Square-cornered enough to belong to the report, round enough to read as a
   control. The old pill belonged to the world this replaces. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;              /* thumb target, iOS HIG floor is 44 */
  padding: 13px 24px;
  border-radius: var(--r-ctl);
  font-family: var(--font);
  font-weight: 600;
  font-size: var(--t-base);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), opacity var(--dur) var(--ease),
              transform .15s var(--ease);
}

.btn-primary { background: var(--signal); color: #fff; }
.btn-primary:hover { background: var(--kadia-teal-dark); }
.btn-primary:active { background: var(--kadia-teal-deep); }

/* The hero's conversion CTA. Reworked at the lawyer's explicit request for a
   button visitors notice right away - supersedes an earlier "no pulsing
   ring" minimalism call. Uses a soft breathing glow plus a light shimmer
   sweep rather than an expanding ring, so it reads as premium rather than
   as the dated "radar ping" that call was avoiding. Hover still steps the
   arrow toward the reading direction and lifts the button slightly; both
   loops stop entirely under prefers-reduced-motion. */
.btn-hero-cta {
  position: relative;
  overflow: hidden;
  box-shadow: 0 4px 18px rgba(15, 122, 69, .3);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn-hero-cta:hover { transform: translateY(-2px); box-shadow: 0 8px 26px rgba(15, 122, 69, .42); }
.btn-hero-cta:active { transform: translateY(0); }
.hero-cta-arrow {
  display: inline-block;
  transition: transform var(--dur) var(--ease);
}
.btn-hero-cta:hover .hero-cta-arrow { transform: translateX(-4px); }
.btn-hero-cta::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 25%, rgba(255,255,255,.4) 45%, rgba(255,255,255,.4) 52%, transparent 72%);
  transform: translateX(-120%);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .btn-hero-cta { animation: kadia-cta-glow 2.8s ease-in-out infinite; }
  .btn-hero-cta::after { animation: kadia-cta-shimmer 3.4s ease-in-out infinite; animation-delay: 1s; }
}
@keyframes kadia-cta-glow {
  0%, 100% { box-shadow: 0 4px 18px rgba(15, 122, 69, .3); }
  50% { box-shadow: 0 7px 28px rgba(15, 122, 69, .5); }
}
@keyframes kadia-cta-shimmer {
  0% { transform: translateX(-120%); }
  35%, 100% { transform: translateX(120%); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-cta-arrow { transition: none; }
  .btn-hero-cta { animation: none; }
  .btn-hero-cta::after { display: none; }
}

.btn-outline {
  background: var(--plate);
  color: var(--ink);
  border-color: var(--rule);
}
.btn-outline:hover { border-color: var(--ink); }

.btn-secondary { background: var(--ink); color: var(--paper); }
.btn-secondary:hover { background: #000; }

.btn-ghost {
  background: transparent;
  color: var(--ink-2);
  padding: 11px 14px;
  min-height: 44px;
}
.btn-ghost:hover { color: var(--ink); background: var(--paper-dim); }

/* The language switch is a real segmented control: both languages are shown
   at once, side by side, with a sliding dark thumb marking the active one -
   not a single button that names only the *other* language, which read as
   an action ("switch to Arabic") rather than a state ("Hebrew is active"). */
.lang-toggle-seg {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.lang-seg-thumb {
  position: absolute;
  top: 3px; bottom: 3px;
  inset-inline-start: 3px;
  width: calc(50% - 4px);
  background: var(--ink);
  border-radius: 999px;
  transition: inset-inline-start .28s var(--ease);
  z-index: 0;
}
.lang-toggle-seg:has(.lang-seg-btn[data-lang="ar"][aria-pressed="true"]) .lang-seg-thumb {
  inset-inline-start: calc(50% + 1px);
}
.lang-seg-btn {
  position: relative;
  z-index: 1;
  border: none;
  background: transparent;
  font-family: var(--font);
  font-size: var(--t-sm);
  font-weight: 700;
  color: var(--ink-3);
  cursor: pointer;
  padding: 7px 14px;
  min-height: 38px;
  border-radius: 999px;
  transition: color .2s ease, transform .15s ease;
}
.lang-seg-btn[aria-pressed="true"] { color: #fff; }
@media (prefers-reduced-motion: reduce) {
  .lang-seg-thumb { transition: none; }
}

.btn-danger {
  background: var(--plate);
  color: var(--stop);
  border-color: #e8bdb9;
}
.btn-danger:hover { background: var(--stop-tint); border-color: var(--stop); }

.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-block { width: 100%; }
.small-btn { min-height: 36px; padding: 7px 13px; font-size: var(--t-sm); }
/* ---------- Hero ---------- */
/* Flat instrument paper. The interest belongs to the report on the right, not
   to a wash behind it. */
.hero {
  background: var(--paper);
  color: var(--ink);
  padding: 72px 0 64px;
  border-bottom: 1px solid var(--rule);
}
.hero .container {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 56px;
  align-items: center;
}

.hero h1 {
  font-size: var(--t-4xl);
  line-height: 1.14;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 20px;
  letter-spacing: -.025em;
}
.hero p.lead {
  font-size: var(--t-lg);
  color: var(--ink-2);
  margin: 0;
  line-height: 1.68;
  max-width: 46ch;
}

.hero-actions {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin-top: 30px;
}
.btn-hero-cta { font-size: var(--t-lg); padding: 16px 30px; min-height: 56px; }

.hero-trust-list {
  display: flex; flex-wrap: wrap; gap: 8px 22px;
  margin: 14px 0 0;
}
.hero-trust-list li {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-2);
}
.hero-trust-list .ico { color: var(--signal); flex: none; font-size: 1.05rem; }

/* Three facts about the check, set as a definition list because that is what
   they are — not three cards of icon + heading + text. */
.hero-facts {
  display: flex; flex-wrap: wrap; gap: 32px;
  margin: 40px 0 0; padding-top: 24px;
  border-top: 1px solid var(--rule);
}
.hero-facts div { display: flex; flex-direction: column; gap: 2px; }
.hero-facts dt {
  font-size: 1.6rem; font-weight: 700; line-height: 1.1;
  letter-spacing: -.02em; color: var(--ink);
}
.hero-facts dd { margin: 0; font-size: var(--t-sm); color: var(--ink-3); }

.hero-warning {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 26px;
  font-size: var(--t-md); font-weight: 500; line-height: 1.6;
  color: var(--stop);
  max-width: 48ch;
}
.hero-warning .ico { font-size: 1.05rem; margin-top: .1em; }

/* ---------- the inspection report ---------- */
/* Still used by app.html's step-3 "analyzing" screen (a real, once-only
   reveal driven by that page's own script) - kept in full even though the
   hero itself no longer uses it (see .scan-mockup below, restored
   2026-08-22). Ink border because a report's edge is not a hairline. */
.report {
  background: var(--plate);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-plate);
  overflow: hidden;
  min-width: 0;
}
.report-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 13px 16px;
  border-bottom: 1px solid var(--rule-strong);
}
.report-title {
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink);
}
.report-ref { font-size: var(--t-xs); font-weight: 600; color: var(--ink-3); letter-spacing: .08em; }

.report-rows { display: flex; flex-direction: column; }
.report-row {
  display: flex; align-items: center; gap: 11px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-md);
}
.report-row:last-child { border-bottom: 0; }
.report-mark { font-size: 1.05rem; color: #b9c0ba; }
.report-label { flex: 1; min-width: 0; font-weight: 500; color: var(--ink-3); }
.report-verdict {
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: .05em; color: var(--ink-3);
  opacity: 0;
}

/* resolved states — set by the inline script one row at a time */
.report-row.is-checked .report-label { color: var(--ink); }
.report-row.is-checked .report-verdict { opacity: 1; }
.report-row.is-checked[data-finding="1"] .report-mark { color: var(--signal); }
.report-row.is-checked[data-finding="1"] .report-verdict { color: var(--signal); font-weight: 700; }
.report-row.is-checked[data-finding="0"] .report-mark { color: #9aa39c; }

@media (prefers-reduced-motion: no-preference) {
  .report-mark, .report-verdict { transition: color .2s var(--ease), opacity .2s var(--ease); }
  .report-label { transition: color .2s var(--ease); }
}

.report-verdict-bar {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 6px 12px; flex-wrap: wrap;
  padding: 14px 16px;
  background: var(--ink); color: var(--on-ink);
  font-size: var(--t-md);
}
.report-verdict-bar > span { color: var(--on-ink-dim); }
.report-verdict-bar strong { font-size: var(--t-lg); font-weight: 700; color: var(--on-ink); min-width: 0; }

/* With no JS the report must still read as a finished document rather than an
   empty checklist, so every row shows its result immediately. */
html:not(.kadia-anim) .report-row .report-verdict { opacity: 1; }
html:not(.kadia-anim) .report-row .report-label { color: var(--ink); }
html:not(.kadia-anim) .report-row[data-finding="1"] .report-mark { color: var(--signal); }
html:not(.kadia-anim) .report-row[data-finding="1"] .report-verdict { color: var(--signal); font-weight: 700; }

/* ---------- the hero ticket mockup (restored 2026-08-22) ---------- */
/* Brought back at the user's explicit request: the flat inspection-report
   widget above read as too cold on its own, and this - a tinted card, a
   scanning beam, checkmarks landing one at a time, a rubber stamp slamming
   down on a loop - is the one deliberate exception to the flat/paper/no-
   shadow rules everywhere else on the site. Same markup, same animations,
   same tokens (--kadia-teal-tint / --kadia-navy / --kadia-teal-dark /
   --kadia-danger are all still-live aliases onto the current signal/ink/stop
   tokens, so this reads as this system's own colors, not a foreign palette
   pasted back in) as the pre-redesign version - only the checkmark glyph
   changed from a literal "✓" character to the site's own drawn .ico-check
   mask, since a text glyph baked into markup is exactly the anti-pattern
   the rest of this redesign eliminated. */
.scan-mockup { width: 100%; max-width: 320px; margin: 0 auto; }

.scan-card {
  position: relative;
  background: var(--kadia-teal-tint);
  border-radius: 28px;
  padding: 30px 22px 22px;
  box-shadow: var(--shadow-lg);
}
.scan-card::before, .scan-card::after {
  content: ""; position: absolute; pointer-events: none;
  width: 22px; height: 22px;
  border: 3px solid var(--kadia-teal);
  border-radius: 5px;
  opacity: .55;
}
.scan-card::before { top: 14px; inset-inline-start: 14px; border-inline-end: none; border-bottom: none; }
.scan-card::after { bottom: 14px; inset-inline-end: 14px; border-inline-start: none; border-top: none; }

.ticket {
  position: relative;
  background: #fff;
  border-radius: 8px 8px 22px 22px;
  padding: 14px 16px 16px;
  box-shadow: 0 6px 20px rgba(19, 23, 26, 0.1);
}
/* torn-perforation edge, as if this card were pulled from a ticket book -
   the "holes" are just the card's own tint color showing through */
.ticket-perf {
  position: absolute;
  top: -7px; left: 10px; right: 10px; height: 14px;
  background-image: radial-gradient(circle 7px, var(--kadia-teal-tint) 7px, transparent 7.4px);
  background-size: 20px 14px;
  background-repeat: repeat-x;
  pointer-events: none;
}
.ticket-inner { position: relative; overflow: hidden; border-radius: 4px; }
.ticket-header {
  display: flex; align-items: center; gap: 8px;
  padding-bottom: 10px; margin-bottom: 4px;
  border-bottom: 1.5px dashed var(--kadia-border);
}
.ticket-emblem {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  background: var(--kadia-navy); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: .8rem;
}
.ticket-header-text { font-weight: 800; color: var(--kadia-navy); font-size: .88rem; }

.ticket-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 0; font-size: .82rem; }
.ticket-label { color: var(--kadia-text-muted); }
.ticket-row-right { display: flex; align-items: center; gap: 5px; }
.ticket-value { font-weight: 700; color: var(--kadia-text); font-variant-numeric: tabular-nums; }
.ticket-row-amount .ticket-value { color: var(--kadia-danger); font-size: 1rem; font-weight: 800; }
.ticket-check { color: var(--kadia-teal-dark); opacity: 0; transform: scale(.5); }
.ticket-row-1 .ticket-check { animation: ticketCheck1In 7s ease-out infinite; }
.ticket-row-2 .ticket-check { animation: ticketCheck2In 7s ease-out infinite; }
.ticket-row-3 .ticket-check { animation: ticketCheck3In 7s ease-out infinite; }
.ticket-row-4 .ticket-check { animation: ticketCheck4In 7s ease-out infinite; }

.ticket-barcode {
  height: 20px; margin-top: 10px; border-radius: 2px; opacity: .35;
  background: repeating-linear-gradient(90deg,
    var(--kadia-navy) 0 2px, transparent 2px 5px,
    var(--kadia-navy) 5px 6px, transparent 6px 10px,
    var(--kadia-navy) 10px 13px, transparent 13px 15px,
    var(--kadia-navy) 15px 16px, transparent 16px 20px);
}

.scan-beam {
  position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, transparent, var(--kadia-teal-light), var(--kadia-teal), var(--kadia-teal-light), transparent);
  box-shadow: 0 0 12px 2px rgba(15, 122, 69, .55);
  opacity: 0;
  animation: scanSweep 7s ease-in-out infinite;
}

/* the signature moment: a round rubber stamp slams onto the ticket at an
   angle once every field has been verified */
.ticket-stamp {
  position: absolute; top: 54%; left: 50%; width: 136px; height: 136px;
  border-radius: 50%; border: 3px solid var(--kadia-teal-dark);
  color: var(--kadia-teal-dark); background: rgba(255,255,255,.94);
  display: flex; align-items: center; justify-content: center;
  text-align: center; font-weight: 800; font-size: .82rem; line-height: 1.4;
  box-shadow: 0 3px 10px rgba(0, 137, 122, .25);
  opacity: 0; transform: translate(-50%, -50%) rotate(-16deg) scale(1.4);
  animation: stampSlam 7s cubic-bezier(.34,1.56,.64,1) infinite;
  pointer-events: none;
}
.ticket-stamp .stamp-num { color: var(--kadia-danger); font-size: 1.35em; font-weight: 900; }

@keyframes scanSweep {
  0%   { top: 0%;  opacity: 0; }
  3%   { opacity: 1; }
  30%  { top: 96%; opacity: 1; }
  34%  { top: 96%; opacity: 0; }
  100% { top: 0%;  opacity: 0; }
}
@keyframes ticketCheck1In {
  0%, 9%    { opacity: 0; transform: scale(.5); }
  14%, 90%  { opacity: 1; transform: scale(1); }
  96%, 100% { opacity: 0; transform: scale(.5); }
}
@keyframes ticketCheck2In {
  0%, 15%   { opacity: 0; transform: scale(.5); }
  20%, 90%  { opacity: 1; transform: scale(1); }
  96%, 100% { opacity: 0; transform: scale(.5); }
}
@keyframes ticketCheck3In {
  0%, 21%   { opacity: 0; transform: scale(.5); }
  26%, 90%  { opacity: 1; transform: scale(1); }
  96%, 100% { opacity: 0; transform: scale(.5); }
}
@keyframes ticketCheck4In {
  0%, 27%   { opacity: 0; transform: scale(.5); }
  32%, 90%  { opacity: 1; transform: scale(1); }
  96%, 100% { opacity: 0; transform: scale(.5); }
}
@keyframes stampSlam {
  0%, 54%  { opacity: 0; transform: translate(-50%,-50%) rotate(-16deg) scale(1.5); }
  60%      { opacity: 1; transform: translate(-50%,-50%) rotate(-9deg) scale(.92); }
  65%      { transform: translate(-50%,-50%) rotate(-13deg) scale(1.04); }
  70%, 90% { opacity: 1; transform: translate(-50%,-50%) rotate(-11deg) scale(1); }
  96%, 100% { opacity: 0; transform: translate(-50%,-50%) rotate(-11deg) scale(1.08); }
}

@media (prefers-reduced-motion: reduce) {
  .scan-beam { display: none; }
  .ticket-check, .ticket-stamp { animation: none; }
  .ticket-check { opacity: 1; transform: scale(1); }
  .ticket-stamp { opacity: 1; transform: translate(-50%,-50%) rotate(-11deg) scale(1); }
}

@media (max-width: 920px) {
  .hero { padding: 40px 0 48px; }
  .hero .container { grid-template-columns: 1fr; gap: 34px; }
  .hero h1 { font-size: 2.05rem; }
  .hero p.lead { font-size: var(--t-base); max-width: none; }
  .hero-facts { gap: 22px; margin-top: 30px; padding-top: 20px; }
  .hero-facts dt { font-size: 1.35rem; }
  .hero-actions { gap: 12px; }
  .btn-hero-cta { width: 100%; }
  .hero-trust-list { justify-content: center; }
  .scan-mockup { max-width: 280px; margin: 34px auto 0; }
}
@media (max-width: 480px) {
  .hero h1 { font-size: 1.85rem; }
  .hero-facts { gap: 0; }
  .hero-facts div {
    flex: 1 1 100%;
    flex-direction: row; align-items: baseline; gap: 10px;
    padding: 9px 0; border-bottom: 1px solid var(--rule);
  }
  .hero-facts div:last-child { border-bottom: 0; }
  .hero-facts dt { font-size: 1.1rem; min-width: 3.2em; }
}

/* ---------- Sections ---------- */
/* Deliberately NON-uniform vertical rhythm: a flat `64px` everywhere made the
   page read as a stack of interchangeable slabs. Each section now gets the
   breathing room its content actually needs, and the alternating white/paper
   banding (set per-section below) gives the eye a place to rest between them. */
section { padding: 72px 0; scroll-margin-top: 90px; }
#how       { padding: 80px 0 88px; background: var(--kadia-card); }
#integrity { padding: 76px 0; background: var(--kadia-bg); }
#violations{ padding: 64px 0 68px; background: var(--kadia-card); }
#pricing   { padding: 78px 0 84px; background: var(--kadia-bg); }
/* pricing -> FAQ is one continuous "still deciding?" beat, so the seam
   between them is tightened rather than given the full section gap */
#faq       { padding: 68px 0 44px; background: var(--kadia-card); }
.section-disclaimer { padding: 40px 0 64px; background: var(--kadia-card); }

.section-title { margin-bottom: 40px; max-width: 62ch; }
/* text-wrap:balance (with a bounded measure, and natural wrapping as the
   fallback where unsupported) - the pricing heading in particular used to
   drop a single orphan word onto its second line */
.section-title h2 {
  font-size: var(--t-2xl); font-weight: 700; color: var(--ink);
  margin-bottom: 10px; letter-spacing: -.02em; line-height: 1.24;
  max-inline-size: 34ch; text-wrap: balance;
}
.section-title p { color: var(--ink-2); font-size: var(--t-base); max-width: 60ch; margin: 0; }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }

.card {
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 24px;
  box-shadow: none;
}

/* An outlined mark, not a filled tile: this world draws with line weight. */
.icon-circle {
  width: 44px; height: 44px;
  border-radius: var(--r-plate);
  border: 1px solid var(--signal);
  background: transparent;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.35rem;
  color: var(--signal);
  margin-bottom: 14px;
}
.icon-circle svg { display: block; }

.about-card {
  background: var(--kadia-card);
  border: 1px solid var(--kadia-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 30px;
  display: flex;
  gap: 22px;
  align-items: flex-start;
  max-width: 760px;
  margin: 0 auto;
}
.about-card .icon-circle { margin-bottom: 0; flex-shrink: 0; width: 64px; height: 64px; font-size: 1.9rem; }
.about-card h3 { color: var(--kadia-navy); font-size: 1.15rem; margin: 0; }
.about-card p { color: var(--kadia-text-muted); line-height: 1.8; }

@media (max-width: 600px) {
  .about-card { flex-direction: column; text-align: center; padding: 22px; }
  .about-card .icon-circle { margin: 0 auto; }
}

/* ---------- "how it works": an ordered process ---------- */
/* This is a sequence, so it is an <ol> with a rule running through it, not
   three identical cards standing side by side. The numbers earn their place
   here because the order is real information: no draft before the check, no
   check before the details. */
.process {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  position: relative;
  counter-reset: none;
}
.process-step {
  position: relative;
  display: flex; flex-direction: column; gap: 14px;
  padding: 0 28px;
  border-inline-start: 1px solid var(--rule);
}
.process-step:first-child { border-inline-start: 0; padding-inline-start: 0; }
.process-step:last-child { padding-inline-end: 0; }

.process-num {
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink);
  border-radius: var(--r-plate);
  font-size: var(--t-base); font-weight: 700;
  color: var(--ink);
}
.process-body h3 {
  font-size: var(--t-xl); font-weight: 700;
  color: var(--ink); margin-bottom: 8px; letter-spacing: -.015em;
}
.process-body p { color: var(--ink-2); line-height: 1.7; font-size: var(--t-md); }

@media (max-width: 860px) {
  .process { grid-template-columns: 1fr; }
  .process-step {
    flex-direction: row; align-items: flex-start; gap: 16px;
    padding: 20px 0; border-inline-start: 0;
    border-top: 1px solid var(--rule);
  }
  .process-step:first-child { border-top: 0; padding-top: 0; }
  .process-num { flex: none; }
}

/* ---------- integrity: an inspection-report supplement ---------- */
/* This used to be a rounded, glass-on-navy panel left over from the old
   gradient world - the one heavy, dark thing on a page that otherwise
   argues for flat paper and ink. It is now just another plate: paper-dim
   ground, plate cards, one hairline, the same vocabulary as the report
   above it. */
.integrity-panel {
  position: relative;
  background: var(--paper-dim);
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 54px 46px 48px;
}
.integrity-head { text-align: center; margin-bottom: 38px; }
.integrity-head h2 { font-size: 2.05rem; font-weight: 800; color: var(--ink); margin-bottom: 12px; letter-spacing: -.015em; }
.integrity-head p { color: var(--ink-2); font-size: 1.05rem; max-width: 58ch; margin: 0 auto; }
.integrity-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.integrity-item {
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 26px 24px;
  transition: border-color .18s ease;
}
.integrity-item:hover { border-color: var(--signal); }
.integrity-item h3 { color: var(--ink); font-size: 1.12rem; margin-bottom: 8px; }
.integrity-item p { color: var(--ink-2); line-height: 1.8; }
.integrity-item .fine-print { color: var(--ink-3); font-size: .86em; }
@media (max-width: 820px) {
  .integrity-panel { padding: 38px 22px 34px; }
  .integrity-head h2 { font-size: 1.6rem; }
  .integrity-grid { grid-template-columns: 1fr; }
}

/* ---------- violations chip grid ---------- */
/* the icon gets its own tinted tile inside the chip so the row reads as a
   set of labelled categories rather than a bag of loose emoji + text */
.chip-grid { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; max-width: 900px; margin: 0 auto; }
.chip {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--kadia-card);
  border: 1px solid var(--kadia-border);
  padding: 9px 18px 9px 10px;
  border-radius: var(--r-plate);
  font-weight: 700;
  color: var(--kadia-navy);
  box-shadow: 0 1px 2px rgba(19, 23, 26, .04);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease, background .15s ease;
}
/* a compact pill label must never wrap to a second line - the collection
   itself reflows (flex-wrap) instead */
.chip-label { white-space: nowrap; min-width: 0; }
.chip-ico {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 30px; height: 30px; border-radius: 10px;
  background: var(--kadia-teal-tint);
  font-size: .95rem;
  transition: background .15s ease, transform .2s var(--ease);
}
.chip:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(19, 23, 26, .10);
  border-color: var(--kadia-teal-light);
}
.chip:hover .chip-ico { transform: scale(1.1) rotate(-4deg); }
@media (prefers-reduced-motion: no-preference) {
  .chip-grid .chip {
    animation: kadia-tile-pop .38s var(--ease) both;
    animation-delay: calc(var(--tile-i, 0) * 45ms);
  }
}

/* Bigger, filled category cards on mobile instead of a wrapped row of
   compact chips - a UX pattern noted from a competitor's mobile app
   (lofrayer.app), applied here as a layout/interaction idea only: this
   site's own icon set, colors, copy and markup, not their content. A grid
   of large icon-led color blocks reads faster at a glance on a phone than
   a row of small pills; the compact chip row still fits comfortably at
   desktop widths, so it's kept there unchanged. */
@media (max-width: 767px) {
  .chip-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; max-width: none; }
  .chip {
    flex-direction: column; justify-content: center; gap: 8px;
    aspect-ratio: 1;
    padding: 10px 6px;
    border: none;
    box-shadow: none;
    color: #fff;
  }
  .chip:hover { transform: none; box-shadow: none; }
  .chip-label { white-space: normal; text-align: center; font-size: .8rem; line-height: 1.25; }
  .chip[data-value="parking"] .chip-ico,
  .chip[data-value="red_white"] .chip-ico,
  .chip[data-value="lpr_camera"] .chip-ico,
  .chip[data-value="public_transit_lane"] .chip-ico,
  .chip[data-value="officer"] .chip-ico,
  .chip[data-value="scooter"] .chip-ico,
  .chip[data-value="airport"] .chip-ico,
  .chip[data-value="other"] .chip-ico {
    width: 36px; height: 36px;
    background: rgba(255, 255, 255, .22);
  }
  .chip[data-value="parking"] .chip-ico::before,
  .chip[data-value="red_white"] .chip-ico::before,
  .chip[data-value="lpr_camera"] .chip-ico::before,
  .chip[data-value="public_transit_lane"] .chip-ico::before,
  .chip[data-value="officer"] .chip-ico::before,
  .chip[data-value="scooter"] .chip-ico::before,
  .chip[data-value="airport"] .chip-ico::before,
  .chip[data-value="other"] .chip-ico::before {
    width: 20px; height: 20px;
  }
  .chip[data-value="parking"] { background: var(--cat-parking); }
  .chip[data-value="red_white"] { background: var(--cat-red_white); }
  .chip[data-value="lpr_camera"] { background: var(--cat-lpr_camera); }
  .chip[data-value="public_transit_lane"] { background: var(--cat-public_transit_lane); }
  .chip[data-value="officer"] { background: var(--cat-officer); }
  .chip[data-value="scooter"] { background: var(--cat-scooter); }
  .chip[data-value="airport"] { background: var(--cat-airport); }
  .chip[data-value="other"] { background: var(--cat-other); }
}
.chip:hover .chip-ico { background: var(--kadia-teal-light); }

/* ---------- category bottom sheet ---------- */
/* A UX pattern noted from a competitor's mobile app: the "start" actions
   open this instead of jumping straight to the wizard. Mobile-only (see
   the JS guard in index.html) - a bottom sheet is a mobile pattern, so
   desktop's hero CTA still goes straight to /app. */
.category-sheet { position: fixed; inset: 0; z-index: 200; }
.category-sheet-backdrop {
  position: absolute; inset: 0; border: none; padding: 0; cursor: pointer;
  background: rgba(19, 23, 26, .5);
  opacity: 0; transition: opacity .22s ease;
}
.category-sheet.is-open .category-sheet-backdrop { opacity: 1; }
.category-sheet-panel {
  position: absolute; inset-inline: 0; bottom: 0; z-index: 1;
  max-height: 85dvh; overflow-y: auto;
  background: var(--paper);
  border-radius: 20px 20px 0 0;
  padding: 10px 20px calc(20px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -8px 30px rgba(19, 23, 26, .25);
  transform: translateY(100%);
  transition: transform .26s cubic-bezier(.22, .61, .36, 1);
}
.category-sheet.is-open .category-sheet-panel { transform: translateY(0); }
.category-sheet-handle {
  width: 40px; height: 4px; border-radius: 999px;
  background: var(--rule); margin: 0 auto 14px;
}
.category-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.category-sheet-head h2 { font-size: var(--t-xl); font-weight: 700; color: var(--ink); margin: 0; }
.category-sheet-close {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--paper-dim); color: var(--ink-2); border: none; cursor: pointer;
}
.category-sheet-sub { color: var(--ink-2); font-size: var(--t-md); margin: 6px 0 18px; }
.category-sheet .chip-grid { margin: 0 0 16px; }
.category-sheet-skip {
  display: block; text-align: center;
  padding: 12px; font-size: var(--t-sm); font-weight: 600; color: var(--ink-3);
}

/* ---------- pricing ---------- */
.price-grid { align-items: stretch; }
.price-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column;
  text-align: center;
  padding: 34px 26px 28px;
  transition: border-color .2s ease;
}
.price-card:hover { border-color: var(--signal); }
.price-card h3 { font-size: 1.1rem; color: var(--kadia-navy); margin-bottom: 10px; }
.price-card > p { font-size: .94rem; line-height: 1.7; }
/* the CTA sits on the card floor so all three buttons line up across the row
   regardless of how much copy each tier carries */
.price-card .btn { margin-top: auto; }

.price-card.highlight {
  border: 2px solid var(--signal);
  /* extra head room so the "most popular" ribbon never crowds the tier name */
  padding-top: 54px;
}
/* a full-width gradient cap: the recommended tier is identifiable from the
   corner of the eye, before any text is read */
.price-card.highlight::before {
  content: ""; position: absolute; top: 0; inset-inline: 0; height: 6px;
  background: var(--signal);
}
.price-card.highlight .price-tag { color: var(--kadia-teal-deep, var(--kadia-teal-dark)); }
.price-card.highlight .btn-primary { background: var(--signal); box-shadow: none; }
@media (min-width: 769px) {
  .price-card.highlight { transform: scale(1.05); z-index: 1; }
  .price-card.highlight:hover { transform: scale(1.05) translateY(-5px); }
}

/* marks the mail tier as an add-on rather than a standalone plan - it is the
   only card with no CTA, and without this it just looked unfinished */
.price-addon-tag {
  /* align-self is required: the card is a flex column, so a plain
     inline-block child stretches to the full card width */
  display: inline-block; align-self: center;
  font-size: .72rem; font-weight: 800; letter-spacing: .05em;
  color: var(--kadia-gold-text, var(--kadia-gold));
  background: rgba(180, 83, 26, .1);
  border-radius: var(--r-plate); padding: 5px 13px;
  margin-bottom: 12px;
}

.price-tag { font-size: 2.6rem; font-weight: 800; color: var(--kadia-navy); line-height: 1.15; margin-bottom: 12px; }
.price-tag small { font-size: .95rem; color: var(--kadia-text-muted); font-weight: 600; }
.price-card ul { text-align: start; margin: 18px 0 22px; border-top: 1px solid var(--kadia-border); padding-top: 16px; }
.price-card li {
  position: relative;
  padding: 8px 0;
  padding-inline-start: 30px;
  color: var(--kadia-text-muted);
  font-size: .94rem; line-height: 1.6;
}
/* The included-in-this-tier mark. Drawn rather than a glyph: a text tick
   renders differently in every font and cannot take the palette. Keeps the
   hanging indent so multi-line items stay aligned. */
.price-card li::before {
  content: "";
  position: absolute; inset-inline-start: 0; top: 10px;
  width: 15px; height: 15px;
  background-color: var(--signal);
  -webkit-mask: var(--i-check) center / contain no-repeat;
          mask: var(--i-check) center / contain no-repeat;
}
.ribbon {
  position: absolute; top: 14px; inset-inline-end: 14px;
  background: var(--signal);
  color: #fff;
  padding: 5px 12px; border-radius: var(--r-plate);
  font-weight: 600; font-size: var(--t-xs); letter-spacing: .04em;
  box-shadow: none;
}

/* ---------- launch "first draft free" promo strip ---------- */
/* Full-bleed announcement bar directly under the header (not inside a
   <section>, so it's exempt from the site-wide `section { padding }` rule
   and always visible on load with no scrolling). Used to be the same dark
   glass panel as the integrity band below it - now a tint of the one signal
   color the whole site already uses for "something real is here", so it
   reads as good news on paper rather than a klaxon. */
.promo-strip {
  position: relative;
  background: var(--signal-tint);
  border-bottom: 1px solid var(--rule);
}
.promo-strip-inner {
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 6px;
  padding: 22px 20px 26px;
}
.promo-strip-live {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--plate); color: var(--signal);
  border: 1px solid var(--signal);
  padding: 3px 13px; border-radius: var(--r-plate);
  font-size: .72rem; font-weight: 800; letter-spacing: .02em;
  text-transform: uppercase;
}
.promo-live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 0 rgba(15, 122, 69, .5);
}
.promo-strip-title {
  color: var(--ink); font-size: 1.28rem; font-weight: 800; margin: 4px 0 0;
}
.promo-strip-subtitle {
  color: var(--ink-2); font-size: 1.08rem; font-weight: 600; line-height: 1.55;
  margin: 2px 0 0; max-width: 620px;
}
.promo-countdown {
  display: flex; align-items: center; gap: 10px;
  margin: 6px 0 2px;
}
.promo-countdown-unit {
  display: flex; flex-direction: column; align-items: center;
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-field);
  min-width: 56px;
  padding: 6px 4px 5px;
}
.promo-countdown-unit .num {
  color: var(--ink); font-size: 1.3rem; font-weight: 800;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.promo-countdown-unit .lbl {
  color: var(--ink-3); font-size: .64rem; font-weight: 700;
  margin-top: 3px; text-transform: uppercase; letter-spacing: .03em;
}
.promo-countdown-sep {
  color: var(--ink-3); font-size: 1.15rem; font-weight: 800;
  transform: translateY(-6px);
}
.promo-strip-cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--signal); color: #fff;
  font-weight: 800; font-size: .95rem;
  padding: 11px 28px; border-radius: var(--r-ctl);
  margin-top: 10px;
  transition: background .15s ease;
}
.promo-strip-cta:hover { background: var(--kadia-teal-dark); }
.promo-strip-cta-gift { display: inline-block; font-size: 1.05em; }

@media (prefers-reduced-motion: no-preference) {
  /* Two animations, both of which mean something: the dot says the offer is
     running now, the separator says a clock is ticking. The gradient drift,
     the shimmer sweep and the wiggling gift said nothing and were removed. */
  .promo-live-dot { animation: promoLiveDotPulse 2s ease-out infinite; }
  .promo-countdown-sep { animation: promoCountdownBlink 1s step-start infinite; }
}
@keyframes promoCountdownBlink {
  50% { opacity: .25; }
}
@keyframes promoStripGradient {
  0%   { background-position: 0% 50%; }
  100% { background-position: 100% 50%; }
}
@keyframes promoStripShimmer {
  0%   { transform: translateX(-160%) skewX(-20deg); opacity: 0; }
  15%  { opacity: 1; }
  55%  { opacity: 1; }
  70%  { transform: translateX(340%) skewX(-20deg); opacity: 0; }
  100% { transform: translateX(340%) skewX(-20deg); opacity: 0; }
}
@keyframes promoLiveDotPulse {
  0%   { box-shadow: 0 0 0 0 rgba(34, 192, 122, .55); }
  70%  { box-shadow: 0 0 0 7px rgba(34, 192, 122, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 192, 122, 0); }
}
@keyframes promoGiftWiggle {
  0%, 82%, 100% { transform: rotate(0deg); }
  86%  { transform: rotate(-12deg); }
  90%  { transform: rotate(10deg); }
  94%  { transform: rotate(-6deg); }
  97%  { transform: rotate(0deg); }
}

@media (max-width: 640px) {
  .promo-strip-inner { padding: 18px 16px 22px; }
  .promo-strip-title { font-size: 1.08rem; }
  .promo-strip-subtitle { font-size: .96rem; }
  .promo-countdown-unit { min-width: 46px; padding: 5px 3px 4px; }
  .promo-countdown-unit .num { font-size: 1.1rem; }
  .promo-countdown { gap: 7px; }
}

/* ---------- FAQ ---------- */
/* was a bare list of hairline-separated text rows that read as unstyled
   leftovers next to the rest of the page; now each question is a real
   card that visibly opens, with a teal state change on the open one */
.faq-list { display: flex; flex-direction: column; gap: 12px; }
.faq-item {
  background: var(--kadia-card);
  border: 1px solid var(--kadia-border);
  border-radius: 16px;
  box-shadow: 0 1px 2px rgba(19, 23, 26, .04);
  transition: background .15s ease, border-color .15s ease, box-shadow .18s ease;
}
.faq-item:hover { border-color: var(--kadia-teal-light); box-shadow: 0 6px 18px rgba(19, 23, 26, .07); }
.faq-item.open {
  background: var(--kadia-teal-tint);
  border-color: var(--kadia-teal);
  box-shadow: 0 10px 24px rgba(15, 122, 69, .12);
}
/* a real <button>, not a click-handled <div>: the old markup was unreachable
   by keyboard and announced nothing about its expanded state */
.faq-q {
  display: flex; width: 100%; justify-content: space-between; align-items: center; gap: 14px;
  background: none; border: 0; margin: 0;
  padding: 18px 22px;
  font: inherit; font-weight: 700; color: var(--kadia-navy);
  text-align: start; line-height: 1.5; cursor: pointer;
}
.faq-q:focus-visible { outline: 2px solid var(--kadia-teal); outline-offset: -3px; border-radius: 15px; }
.faq-a {
  max-height: 0; overflow: hidden;
  padding-inline: 22px;
  color: var(--kadia-text-muted);
  transition: max-height .3s ease;
  line-height: 1.8;
}
.faq-item.open .faq-q { padding-bottom: 13px; }
.faq-item.open .faq-a {
  max-height: 900px;
  padding-top: 14px; padding-bottom: 20px;
  border-top: 1px solid rgba(15, 122, 69, .22);
}
.faq-item.open .faq-q .arrow { transform: rotate(180deg); background: var(--kadia-teal); color: #fff; }
.arrow {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--kadia-bg-dim, var(--kadia-bg)); color: var(--kadia-navy);
  font-size: .85rem; transition: transform .2s ease, background .15s ease, color .15s ease;
}
.faq-item:hover .arrow { background: var(--kadia-teal-tint); color: var(--kadia-teal-deep, var(--kadia-teal-dark)); }

/* ---------- disclaimer ---------- */
/* the legal small print is now clearly labelled as a notice (icon + accent
   bar) instead of an anonymous beige rectangle sitting at the page floor */
.disclaimer {
  position: relative;
  display: flex; gap: 16px; align-items: flex-start;
  background: var(--caution-tint);
  border: 1px solid #ecdfa8;
  border-radius: 20px;
  padding: 22px 26px 22px 26px;
  color: #5b4b16;
  font-size: 0.92rem;
  line-height: 1.75;
  max-width: 980px; margin: 0 auto;
  box-shadow: none;
}
.disclaimer::before {
  content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; width: 5px;
  border-start-start-radius: 20px; border-end-start-radius: 20px;
  background: var(--caution);
}
.disclaimer-icon {
  flex: none;
  width: 40px; height: 40px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: #f6e9bd; font-size: 1.25rem;
}
.disclaimer-body { min-width: 0; }
.disclaimer strong { color: #4a3d10; }

/* ---------- footer ---------- */
/* rebuilt from a two-column stub (logo on one side, three stacked links on
   the other, with a wide empty gutter in between) into a real navigable
   footer: brand + promise, a legal column, a section column, and a hairline
   bottom bar carrying the copyright. */
footer.site-footer {
  position: relative;
  background: var(--ink);
  color: var(--on-ink-dim);
  padding: 54px 0 26px;
  margin-top: 0;
  font-size: 0.92rem;
}
footer.site-footer::before {
  content: ""; position: absolute; top: 0; inset-inline: 0; height: 3px;
  background: var(--caution);
  opacity: .85;
}
footer.site-footer a { color: var(--on-ink-dim); opacity: 0.85; transition: opacity .15s ease, color .15s ease; }
footer.site-footer a:hover { opacity: 1; color: var(--kadia-teal-light); text-decoration: underline; }
footer.site-footer .cols {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 30px 40px;
  align-items: start;
}
/* .brand is the logo lockup itself (circle-mark <img> + "ADIA." text), a
   flex row - so align-items here is the mark's vertical alignment against the
   text, NOT the column's horizontal alignment (that's the grid's own
   align-items:start above). flex-start top-aligned the 34px mark against the
   shorter text line-box, floating "ADIA." ~7px above the circle's centre and
   breaking the "KADIA." lockup in the footer (header was unaffected - it keeps
   the base .brand centre). Match it back to centre. */
footer.site-footer .brand { align-items: center; }
.footer-tagline { color: rgba(207, 199, 221, .72); margin-top: 12px; line-height: 1.75; max-width: 38ch; }
.footer-col-title {
  color: #fff; font-weight: 800; font-size: .82rem; letter-spacing: .07em;
  margin-bottom: 14px;
}
.footer-links { display: flex; flex-direction: column; gap: 11px; }
.footer-cta {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 18px;
  background: var(--signal);
  color: #fff !important; opacity: 1 !important;
  border-radius: var(--r-plate); padding: 11px 22px;
  font-weight: 700; font-size: .92rem;
  box-shadow: 0 8px 20px rgba(15, 122, 69, .32);
  transition: transform .15s ease, box-shadow .15s ease;
}
.footer-cta:hover { transform: translateY(-2px); text-decoration: none !important; box-shadow: 0 12px 26px rgba(15, 122, 69, .4); }
.footer-bottom {
  margin-top: 34px; padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, .1);
  display: flex; flex-wrap: wrap; gap: 10px 20px;
  justify-content: space-between; align-items: center;
  color: rgba(207, 199, 221, .6); font-size: .85rem;
}
@media (max-width: 780px) {
  footer.site-footer { padding: 40px 0 22px; }
  footer.site-footer .cols { grid-template-columns: 1fr 1fr; }
  footer.site-footer .cols > :first-child { grid-column: 1 / -1; }
  .disclaimer { flex-direction: column; gap: 12px; padding: 20px; }
}

/* ---------- Wizard (app.html) ---------- */
/* soft ambient wash behind the wizard, echoing the landing hero's own
   background treatment - kept subtle (a wide, low-opacity radial glow) so
   the wizard doesn't read as a flat gray box floating on white the way it
   did before. Scoped to app.html only via body.wizard-page, AND to screen
   only - a class selector on body beats the print reset's plain "body"
   selector on specificity alone regardless of which media block either is
   in, so without this @media screen guard the gradient wash was bleeding
   straight through into the printed/PDF letter (confirmed via a real
   generated PDF during the 2026-08-19 review - the empty-looking tinted
   block at the top of the printed letter was exactly this). */
@media screen {
  body.wizard-page {
    background: var(--paper);
  }
}

.wizard-shell {
  max-width: 800px;
  margin: 36px auto 90px;
  padding: 0 20px;
}
/* step 2 only: extra width for the chat + recap-rail split (see .chat-layout).
   Separate from .wizard-shell-wide, which serves step 1's scan screen. */
@media (min-width: 980px) {
  .wizard-shell.wizard-shell-chat { max-width: 1040px; }
}

#progressBlock { margin-bottom: 22px; }

.progress-header {
  display: flex; align-items: flex-start; gap: 14px;
}
.progress-header-text { min-width: 0; display: flex; flex-direction: column; }
.progress-header-text .step-name {
  font-weight: 800; color: var(--kadia-navy); font-size: 1.4rem; line-height: 1.25;
  animation: kadia-fade-up .35s ease-out both;
}
.progress-header-text .step-count {
  font-size: .74rem; color: var(--signal); font-weight: 800; margin-bottom: 2px;
  text-transform: uppercase; letter-spacing: .06em;
}
.progress-question-count {
  flex: none;
  margin-inline-start: auto;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--signal-tint);
  color: var(--kadia-teal-dark);
  font-size: .78rem; font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- step stepper: circles + connectors, mirrors the wizard's own
   4 real steps (step 5 is a "done" screen, not tracked here - see
   renderProgress() hiding #progressBlock entirely once past DISPLAY_STEPS).
   Nodes are built once and only their data-state flips on every step change,
   so the circle fill / connector color / checkmark pop can all transition
   instead of jumping (a full DOM rebuild would give the browser no "before"
   state to animate from). ---------- */
.progress-track {
  display: flex;
  margin-bottom: 18px;
}
.stepper-item {
  flex: 1;
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  min-width: 0;
}
.stepper-item:not(:first-child)::before {
  content: "";
  position: absolute;
  inset-inline-start: -50%;
  top: 15px;
  width: 100%; height: 2px;
  background: var(--kadia-border);
  transition: background-color .35s var(--ease);
  z-index: 0;
}
.stepper-item[data-state="done"]::before,
.stepper-item[data-state="current"]::before { background: var(--signal); }

.stepper-circle {
  position: relative; z-index: 1;
  flex: none;
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper);
  border: 1.5px solid var(--kadia-border);
  color: var(--kadia-text-muted);
  font-size: .92rem; font-weight: 800;
  transition: background-color .3s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.stepper-item[data-state="current"] .stepper-circle {
  background: var(--ink); border-color: var(--ink); color: #fff;
  transform: scale(1.08);
}
.stepper-item[data-state="done"] .stepper-circle {
  background: var(--signal); border-color: var(--signal); color: #fff;
}
/* "you are here": a live pulsing ring on whichever circle is current, not
   just a one-time pop when it becomes current - the black fill alone read
   as static, no different from a screenshot. Runs continuously for as long
   as this step stays current, stops the moment it flips to done/upcoming. */
@media (prefers-reduced-motion: no-preference) {
  .stepper-item[data-state="current"] .stepper-circle {
    animation: kadia-step-live 1.8s ease-out infinite;
  }
}
@keyframes kadia-step-live {
  0%   { box-shadow: 0 0 0 0 rgba(15, 122, 69, .45); }
  70%  { box-shadow: 0 0 0 8px rgba(15, 122, 69, 0); }
  100% { box-shadow: 0 0 0 0 rgba(15, 122, 69, 0); }
}
.stepper-num { display: block; }
.stepper-check { display: none; font-size: .95rem; transform: scale(.4); opacity: 0; transition: transform .25s var(--ease), opacity .2s ease; }
.stepper-item[data-state="done"] .stepper-num { display: none; }
.stepper-item[data-state="done"] .stepper-check { display: block; transform: scale(1); opacity: 1; }

.stepper-label {
  font-size: .74rem; font-weight: 600; color: var(--kadia-text-muted);
  text-align: center; line-height: 1.3;
  max-width: 84px;
  transition: color .3s ease;
}
.stepper-item[data-state="current"] .stepper-label { color: var(--ink); font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .stepper-circle, .stepper-item::before, .stepper-check, .stepper-label { transition: none; }
}

@media (max-width: 480px) {
  .stepper-circle { width: 27px; height: 27px; font-size: .8rem; }
  .stepper-item:not(:first-child)::before { top: 12.5px; }
  .stepper-label { font-size: .64rem; max-width: 62px; }
  .progress-header-text .step-name { font-size: 1.15rem; }
  .progress-header-text .step-count { font-size: .68rem; }
}

.step2-progress-wrap { margin-bottom: 24px; }
.step2-progress-track { height: 6px; border-radius: 999px; background: var(--kadia-border); overflow: hidden; margin-bottom: 6px; }
.step2-progress-fill { height: 100%; background: var(--kadia-teal); border-radius: 999px; transition: width .3s ease; }
.step2-progress-text { font-size: .82rem; color: var(--kadia-text-muted); font-weight: 700; }

/* ---------- Chat-style questionnaire (step 2) — AI-assistant look ---------- */
/* Desktop split: a reading-width chat column beside a sticky recap rail.
   Before this, the chat stretched the full ~860px card, so the assistant's
   text sat hard against one edge and the user's answers against the other
   with a dead gutter between them - the same "desktop as a stretched phone"
   problem step 1's scan screen already had solved. */
.chat-layout { display: block; }
@media (min-width: 980px) {
  .chat-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 280px;
    gap: 34px;
    align-items: start;
  }
  .chat-main { min-width: 0; max-width: 640px; }
}

.chat-rail { display: none; }
@media (min-width: 980px) {
  .chat-rail {
    display: block;
    position: sticky; top: 96px;
    background: var(--kadia-bg);
    border: 1px solid var(--kadia-border);
    border-radius: 20px;
    padding: 20px 20px 18px;
  }
}
.chat-rail-title {
  font-size: .78rem; font-weight: 800; letter-spacing: .05em;
  color: var(--kadia-teal-deep, var(--kadia-teal-dark));
  margin: 0 0 14px;
}
.chat-rail-list { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.chat-rail-row { display: flex; flex-direction: column; gap: 2px; }
.chat-rail-row dt { font-size: .76rem; color: var(--kadia-text-muted); font-weight: 700; }
.chat-rail-row dd { margin: 0; font-size: .95rem; color: var(--kadia-navy); font-weight: 700; }
.chat-rail-note {
  margin: 16px 0 0; padding-top: 14px;
  border-top: 1px solid var(--kadia-border);
  font-size: .78rem; line-height: 1.65; color: var(--kadia-text-muted);
}

.chat-log {
  display: flex; flex-direction: column; gap: 22px;
  margin-bottom: 24px; max-height: min(62dvh, 620px); overflow-y: auto;
  padding: 14px 2px 18px;
  scroll-behavior: smooth;
  /* the log scrolls internally; without this the oldest bubble is simply
     sliced in half at the top edge and reads as a rendering bug rather
     than as scrolled-away history */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 28px);
  mask-image: linear-gradient(to bottom, transparent 0, #000 28px);
}
.chat-log::-webkit-scrollbar { width: 6px; }
.chat-log::-webkit-scrollbar-thumb { background: var(--kadia-border); border-radius: 999px; }
.chat-log::-webkit-scrollbar-thumb:hover { background: var(--kadia-teal-light); }

/* composed entrance: small rise, soft easing, no bounce */
@keyframes kadia-chat-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.chat-bubble { max-width: 88%; animation: kadia-chat-in .38s cubic-bezier(.22, .61, .36, 1) both; }

/* --- assistant: avatar + open text, no bubble fill --- */
.chat-bot {
  align-self: flex-start;
  display: flex; align-items: flex-start; gap: 10px;
}
.chat-avatar {
  flex: none; width: 34px; height: 34px; margin-top: 2px;
  border-radius: var(--r-plate);
  border: 1px solid var(--signal);
  background: var(--signal-tint);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--signal);
  user-select: none;
}
/* the inspection mark, so the assistant reads as the thing running the check
   rather than as a generic chat persona */
.chat-avatar::before {
  content: "";
  width: 18px; height: 18px;
  background-color: currentColor;
  -webkit-mask: var(--i-scan) center / contain no-repeat;
          mask: var(--i-scan) center / contain no-repeat;
}
.chat-bot .chat-bubble-inner {
  padding: 5px 0 0;
  color: var(--ink);
  line-height: 1.7; font-size: var(--t-base); font-weight: 500;
}

/* --- user: quiet tinted bubble, focus stays on the assistant --- */
.chat-user { align-self: flex-end; cursor: pointer; }
.chat-user .chat-bubble-inner {
  background: var(--signal-tint);
  border: 1px solid var(--signal);
  color: var(--ink);
  padding: 11px 16px; border-radius: 16px;
  line-height: 1.65; font-size: var(--t-md); font-weight: 500;
  white-space: pre-wrap;
  transition: background var(--dur) var(--ease);
}
.chat-user:hover .chat-bubble-inner { background: #d8ebe1; }
/* edit affordance: a drawn pencil. On touch there is no hover to reveal it,
   so it is always visible there and only hover-revealed on a pointer device. */
.chat-user .chat-bubble-inner::after {
  content: "";
  display: inline-block;
  width: .86em; height: .86em;
  vertical-align: -.1em;
  background-color: var(--kadia-teal-dark);
  -webkit-mask: var(--i-edit) center / contain no-repeat;
          mask: var(--i-edit) center / contain no-repeat;
  margin-inline-start: 8px;
  opacity: .55; transition: opacity var(--dur) var(--ease);
}
.chat-user:hover .chat-bubble-inner::after { opacity: 1; }
@media (hover: hover) { .chat-user .chat-bubble-inner::after { opacity: 0; } }

/* --- quick-reply suggestion chips --- */
.chat-options {
  display: flex; flex-wrap: wrap; gap: 10px;
  align-self: flex-start; max-width: 100%;
  padding-inline-start: 44px; /* aligns under bot text (34px avatar + 10px gap) */
  animation: kadia-chat-in .38s cubic-bezier(.22, .61, .36, 1) .08s both;
}
.chat-option-btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px;
  padding: 11px 18px; border-radius: var(--r-ctl);
  border: 1px solid var(--rule);
  background: var(--plate); color: var(--ink);
  font-weight: 500; font-size: var(--t-md); font-family: inherit; cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.chat-option-btn:hover { border-color: var(--ink); }
.chat-option-btn.selected {
  background: var(--signal-tint);
  border-color: var(--signal);
  color: var(--kadia-teal-deep);
  font-weight: 600;
}
/* a drawn tick, matching every other confirmation mark in the interface */
.chat-multi-btn.selected::before {
  content: "";
  width: .95em; height: .95em; flex: none;
  background-color: var(--signal);
  -webkit-mask: var(--i-check) center / contain no-repeat;
          mask: var(--i-check) center / contain no-repeat;
}

.chat-multiselect, .chat-elaboration {
  align-self: flex-start; width: 100%; max-width: 100%;
  padding-inline-start: 44px; box-sizing: border-box;
  animation: kadia-chat-in .38s cubic-bezier(.22, .61, .36, 1) .08s both;
}
.chat-multiselect .chat-options { padding-inline-start: 0; animation: none; }

.chat-multi-confirm {
  margin-top: 12px;
  min-height: 44px;
  padding: 10px 22px; border: none; border-radius: var(--r-ctl);
  background: var(--signal); color: #fff;
  font-family: inherit; font-weight: 600; font-size: var(--t-md); cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.chat-multi-confirm:hover { background: var(--kadia-teal-dark); }

/* "what applies to you?" checklist (wizard.js CHECKLIST_SHORT): full-width
   rows rather than wrapping chips - the lines are sentences, and a list of up
   to ~14 of them has to scan top-to-bottom on a 375px phone. Same tokens and
   selected state as the chips above; the box draws the same tick. */
.chat-checklist {
  align-self: flex-start; width: 100%; max-width: 100%;
  padding-inline-start: 44px; box-sizing: border-box;
  animation: kadia-chat-in .38s cubic-bezier(.22, .61, .36, 1) .08s both;
}
.chat-checklist-list { display: flex; flex-direction: column; gap: 8px; }
.chat-checklist-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 48px; padding: 11px 14px;
  border: 1px solid var(--rule); border-radius: var(--r-ctl);
  background: var(--plate); color: var(--ink);
  font-family: inherit; font-size: var(--t-md); font-weight: 500; line-height: 1.45;
  text-align: start; cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.chat-checklist-item:hover { border-color: var(--ink); }
.chat-checklist-item:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.chat-checklist-box {
  flex: none; width: 1.25em; height: 1.25em;
  border: 1.5px solid var(--rule); border-radius: 5px; background: var(--plate);
  display: grid; place-items: center;
}
.chat-checklist-item.selected {
  background: var(--signal-tint); border-color: var(--signal);
  color: var(--kadia-teal-deep); font-weight: 600;
}
.chat-checklist-item.selected .chat-checklist-box { background: var(--signal); border-color: var(--signal); }
.chat-checklist-item.selected .chat-checklist-box::after {
  content: ""; width: .8em; height: .8em; background-color: #fff;
  -webkit-mask: var(--i-check) center / contain no-repeat;
          mask: var(--i-check) center / contain no-repeat;
}
@media (max-width: 600px) {
  .chat-checklist { padding-inline-start: 0; }
}

/* --- free-text composer --- */
.chat-composer {
  display: flex; align-items: flex-end; gap: 8px;
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-ctl);
  padding: 6px; padding-inline-start: 14px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* the textarea itself drops its outline, so the wrapper must carry a focus
   indicator that actually meets non-text contrast — not a 12%-alpha haze */
.chat-composer:focus-within {
  border-color: var(--signal);
  box-shadow: 0 0 0 2px var(--signal);
}
.chat-textarea {
  flex: 1; min-width: 0;
  border: none; outline: none; background: transparent;
  resize: none; font-family: inherit; font-size: .95rem; line-height: 1.7;
  color: var(--kadia-text);
  padding: 8px 0; min-height: 24px; max-height: 140px;
  field-sizing: content; /* auto-grow in modern browsers; harmless fallback elsewhere */
}
.chat-textarea::placeholder { color: var(--kadia-text-muted); opacity: .75; }
.chat-elaboration-submit {
  flex: none; width: 44px; height: 44px;
  border: none; border-radius: 9px;
  background: var(--signal); color: #fff; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--dur) var(--ease);
}
.chat-elaboration-submit:hover { background: var(--kadia-teal-dark); }
.chat-elaboration-submit svg { width: 19px; height: 19px; }
.chat-elaboration-skip {
  margin-top: 8px; padding: 4px 2px;
  background: none; border: none;
  color: var(--kadia-text-muted);
  font-family: inherit; font-size: .85rem; font-weight: 600; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.chat-elaboration-skip:hover { color: var(--kadia-teal-dark); }

/* --- typing indicator: avatar + soft pulsing dots, no bubble --- */
.chat-typing .chat-bubble-inner {
  display: inline-flex; align-items: center; padding: 9px 0 0;
}
.chat-typing-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--signal); margin: 0 2.5px; opacity: .3;
  animation: kadia-typing-pulse 1.2s infinite ease-in-out;
}
.chat-typing-dot:nth-child(2) { animation-delay: .18s; }
.chat-typing-dot:nth-child(3) { animation-delay: .36s; }
@keyframes kadia-typing-pulse {
  0%, 100% { opacity: .25; transform: scale(.9); }
  40%      { opacity: 1;   transform: scale(1); }
}

/* .sticky-cta-bar is fixed only up to 767px (see the wizard/account app-bar
   rules) - the default .chat-log max-height above is sized for desktop,
   where nothing overlaps its bottom edge, so anywhere within that same
   767px range needs its own budget that actually reserves room for the bar.
   A real bug found live: without this, 56dvh alone reserved nothing for the
   fixed bar (56px + padding ≈ 84px, the same figure .wizard-card subtracts
   for the same reason) - late in a long question flow, once enough Q&A
   history had accumulated to push the log's own box past that point, the
   newest bubble (in one reproduced case, a multi-select's own "continue"
   button) rendered completely underneath the fixed bar and could not be
   tapped at all. */
@media (max-width: 767px) {
  .chat-log { max-height: calc(56dvh - 84px - env(safe-area-inset-bottom, 0px)); }
}

@media (max-width: 480px) {
  .chat-log { max-height: calc(50dvh - 84px - env(safe-area-inset-bottom, 0px)); gap: 16px; }
  .chat-bubble { max-width: 96%; }
  .chat-bot { gap: 8px; }
  .chat-avatar { width: 28px; height: 28px; }
  .chat-avatar::before { width: 15px; height: 15px; }
  /* reclaim the indent on narrow screens */
  .chat-options, .chat-multiselect, .chat-elaboration { padding-inline-start: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .chat-bubble, .chat-options, .chat-multiselect, .chat-elaboration { animation: none; }
  .chat-typing-dot { animation: none; opacity: .6; }
}

/* an inline gloss of the Hebrew term as it appears on the original (Hebrew) ticket, so the reader can cross-reference it directly - styled as a distinct reference chip rather than blending into the Arabic sentence */
.he-gloss {
  display: inline-block;
  background: var(--kadia-teal-tint);
  color: var(--kadia-teal-dark);
  padding: 1px 8px;
  border-radius: 6px;
  font-size: .85em;
  font-weight: 700;
  margin: 0 2px;
}

.field-invalid { border: 2px solid var(--kadia-danger); border-radius: var(--r-card-sm); padding: 8px; animation: kadia-shake .4s ease; }
@keyframes kadia-shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60% { transform: translateX(4px); }
}

.link-btn {
  background: none; border: none; text-decoration: underline;
  color: inherit; cursor: pointer; font-weight: 700; padding: 0;
  margin-inline-start: 6px; font-size: inherit; font-family: inherit;
}

.kadia-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: var(--kadia-navy); color: #fff;
  padding: 12px 22px; border-radius: var(--r-plate);
  font-weight: 700; font-size: .92rem;
  box-shadow: 0 8px 24px rgba(0,0,0,0.2);
  opacity: 0; transition: opacity .3s ease, transform .3s ease;
  z-index: 9999; pointer-events: none;
  max-width: calc(100vw - 40px); text-align: center;
}
.kadia-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.kadia-toast-error { background: var(--kadia-danger); }

/* floating "contact us" widget - injected by contact-widget.js on every
   customer-facing page. Desktop-only per the office's request (a bottom-left
   fixed circle competes too much with the mobile nav/keyboard on small
   screens) - the same breakpoint already used elsewhere on this site. */
.contact-widget-btn {
  position: fixed; bottom: 24px; left: 24px; z-index: 950;
  width: 56px; height: 56px; border-radius: 50%; border: none;
  background: var(--ink);
  color: #fff; display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 10px 26px rgba(19, 23, 26,0.35);
  transition: transform .15s ease, box-shadow .15s ease;
}
.contact-widget-btn:hover { transform: translateY(-2px); box-shadow: 0 14px 30px rgba(19, 23, 26,0.42); }
.contact-widget-btn::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid var(--kadia-teal); opacity: 0; transition: opacity .15s ease;
}
.contact-widget-btn:focus-visible::after { opacity: 1; }
@media (max-width: 920px) {
  .contact-widget-btn { display: none; }
}

.contact-widget-overlay {
  display: none; position: fixed; inset: 0; z-index: 1200;
  background: rgba(36, 26, 51, 0.55); backdrop-filter: blur(2px);
  align-items: center; justify-content: center; padding: 24px;
}
.contact-widget-overlay.open { display: flex; }
.contact-widget-modal {
  position: relative; background: var(--kadia-card); border-radius: 20px;
  padding: 32px 30px; width: 100%; max-width: 440px; max-height: calc(100vh - 60px);
  overflow-y: auto; box-shadow: 0 24px 60px rgba(0,0,0,0.3);
  /* explicit, not inherited: this card is reused by auth-gate.js on
     lookup.html, whose body sets a light --lk-text color for its own dark
     page background - without this, any plain text dropped in here (e.g.
     #agHint, which has no color rule of its own) silently inherited that
     near-white color and went unreadable on this card's light background. */
  color: var(--kadia-text);
}
.contact-widget-modal h2 { margin: 0 0 18px; color: var(--kadia-navy); font-size: 1.3rem; }
.contact-widget-modal p.hint { color: var(--kadia-text-muted); }
.contact-widget-close {
  position: absolute; top: 14px; inset-inline-end: 14px;
  width: 32px; height: 32px; border-radius: 50%; border: none;
  background: var(--kadia-bg); color: var(--kadia-text-muted);
  font-size: 1.3rem; line-height: 1; cursor: pointer;
}
.contact-widget-close:hover { background: var(--kadia-border); }
.contact-widget-modal .field { margin-bottom: 14px; }
.contact-widget-error {
  background: #fbe9e7; color: var(--kadia-danger); border-radius: 10px;
  padding: 10px 14px; font-size: .88rem; margin-bottom: 14px;
}
.contact-widget-success { text-align: center; padding: 10px 0; }
.contact-widget-success h2 { color: var(--kadia-success); }
.contact-widget-success p { color: var(--kadia-text-muted); margin: 10px 0 22px; }

/* floating accessibility widget - injected by accessibility-widget.js, same
   pattern as the contact widget above, stacked directly on top of it in the
   same bottom-left corner (a legal requirement in Israel: ת"י 5568 / the
   Equal Rights for Persons with Disabilities regulations require an
   accessibility statement reachable from every page - the widget's own
   panel links to it, and it's also present everywhere itself). Desktop AND
   mobile both need this one (unlike the contact button) - accessibility
   accommodations aren't a "nice to have" that mobile visitors can skip. */
/* Mobile-only app-shell navigation - full rules under the ≤767px app-shell
   media query below; hidden by default so it never appears in the desktop
   two-column layout, where the header's own nav already covers this. */
.bottom-tab-bar { display: none; }

/* Small edge-flush tab, not a bold floating circle - a pattern noted from
   a competitor's mobile app: a quiet, standard accessibility icon that
   reads as "this site has an accessibility menu" without competing for
   attention against the primary green CTAs everywhere else on the page.
   Rounded only on the visible (inner) side and flush left:0 with no
   left border, since the screen edge itself reads as the fourth side. */
.a11y-widget-btn {
  position: fixed; bottom: 92px; left: 0; z-index: 950;
  width: 36px; height: 36px;
  border-radius: 0 999px 999px 0;
  border: 1px solid var(--rule); border-inline-start: 0;
  background: var(--plate);
  color: var(--ink-3); display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 2px 8px rgba(19, 23, 26, .12);
  transition: color .15s ease, box-shadow .15s ease;
}
.a11y-widget-btn .ico { width: 20px; height: 20px; }
.a11y-widget-btn:hover { color: var(--ink); box-shadow: 0 4px 14px rgba(19, 23, 26, .18); }
.a11y-widget-btn::after {
  content: ""; position: absolute; inset: -4px; border-radius: 0 999px 999px 0;
  border: 2px solid var(--signal); opacity: 0; transition: opacity .15s ease;
}
.a11y-widget-btn:focus-visible::after { opacity: 1; }
@media (max-width: 920px) {
  /* the contact button hides on mobile (see .contact-widget-btn) - this one
     drops down to take its usual bottom-left spot instead of floating alone
     with an empty gap above it */
  .a11y-widget-btn { bottom: 24px; }
}

.a11y-widget-panel {
  display: none; position: fixed; bottom: 136px; left: 12px; z-index: 1100;
  background: var(--kadia-card); border-radius: 18px; padding: 22px;
  width: 280px; max-width: calc(100vw - 24px); box-shadow: 0 20px 50px rgba(0,0,0,0.25);
}
@media (max-width: 920px) { .a11y-widget-panel { bottom: 68px; } }
.a11y-widget-panel.open { display: block; }
.a11y-widget-panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.a11y-widget-panel-header h2 { margin: 0; font-size: 1.05rem; color: var(--kadia-navy); }
.a11y-widget-close {
  width: 28px; height: 28px; border-radius: 50%; border: none;
  background: var(--kadia-bg); color: var(--kadia-text-muted);
  font-size: 1.15rem; line-height: 1; cursor: pointer;
}
.a11y-widget-close:hover { background: var(--kadia-border); }
.a11y-widget-group { margin-bottom: 14px; }
.a11y-widget-group-label { font-size: .82rem; font-weight: 700; color: var(--kadia-text-muted); margin-bottom: 8px; }
.a11y-widget-font-row { display: flex; gap: 6px; }
.a11y-widget-font-row button {
  flex: 1; border: 1.5px solid var(--kadia-border); background: var(--kadia-card);
  border-radius: 10px; padding: 8px 4px; font-size: .82rem; cursor: pointer; color: var(--kadia-text);
}
.a11y-widget-font-row button.active { border-color: var(--kadia-teal); background: var(--kadia-teal-tint); color: var(--kadia-teal-dark); font-weight: 700; }
.a11y-widget-toggle-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 0; border-bottom: 1px solid var(--kadia-border); font-size: .9rem;
}
.a11y-widget-toggle-row:last-of-type { border-bottom: none; }
.a11y-widget-switch { position: relative; width: 40px; height: 22px; flex: none; }
.a11y-widget-switch input { opacity: 0; width: 0; height: 0; }
.a11y-widget-switch-track {
  position: absolute; inset: 0; background: var(--kadia-border); border-radius: 999px;
  transition: background .15s ease; cursor: pointer;
}
.a11y-widget-switch-track::before {
  content: ""; position: absolute; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; top: 2px; inset-inline-start: 2px; transition: transform .15s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.a11y-widget-switch input:checked + .a11y-widget-switch-track { background: var(--kadia-teal); }
.a11y-widget-switch input:checked + .a11y-widget-switch-track::before { transform: translateX(18px); }
html[dir="rtl"] .a11y-widget-switch input:checked + .a11y-widget-switch-track::before { transform: translateX(-18px); }
.a11y-widget-reset-btn {
  width: 100%; margin-top: 6px; background: none; border: none;
  color: var(--kadia-text-muted); text-decoration: underline; font-size: .85rem;
  cursor: pointer; padding: 6px 0;
}
.a11y-widget-statement-link {
  display: block; text-align: center; margin-top: 12px; padding-top: 14px;
  border-top: 1px solid var(--kadia-border); font-size: .88rem; font-weight: 700;
  color: var(--kadia-teal-dark); text-decoration: none;
}

/* the accessibility modes themselves - applied as classes on <html> by
   accessibility-widget.js, persisted in localStorage. Reusing the site's own
   CSS custom properties for high-contrast (rather than a blanket filter)
   keeps every component's existing styling intact instead of fighting it. */
html.a11y-font-large { font-size: 112.5%; }
html.a11y-font-xlarge { font-size: 125%; }
html.a11y-high-contrast {
  --paper: #ffffff; --paper-dim: #ffffff; --plate: #ffffff;
  --ink: #000000; --ink-2: #000000; --ink-3: #000000;
  --rule: #000000; --rule-strong: #000000;
  --on-ink: #ffffff; --on-ink-dim: #ffffff; --rule-on-ink: #ffffff;
  --signal: #005c33; --signal-tint: #ffffff;
  --caution: #7a3300; --caution-tint: #ffffff;
  --stop: #8c0000; --stop-tint: #ffffff;
  --kadia-bg: #ffffff; --kadia-card: #ffffff; --kadia-text: #000000;
  --kadia-text-muted: #000000; --kadia-border: #000000;
}
html.a11y-high-contrast a { color: #0000ee; text-decoration: underline; }
html.a11y-high-contrast .btn-primary, html.a11y-high-contrast .btn-secondary { background: #000; color: #fff; border-color: #000; }
html.a11y-grayscale { filter: grayscale(1); }
html.a11y-underline-links a { text-decoration: underline !important; }
/* NOT animation:none/transition:none - a real bug, confirmed live: the
   landing page's scroll-reveal sections (.reveal, see above) start at
   opacity:0 and rely on their transition running to ever reach opacity:1.
   Killing the transition outright froze them invisible forever instead of
   skipping the motion - collapsing the duration to near-zero still lets
   them reach their end state, just instantly, which is what "stop
   animations" actually means. Same recipe as the standard
   prefers-reduced-motion snippet, applied as a manual, always-on toggle
   here regardless of the visitor's OS-level setting. */
html.a11y-stop-animations *, html.a11y-stop-animations *::before, html.a11y-stop-animations *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}

.wizard-card {
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 32px;
}

/* the 6 wizard step cards specifically (every .step is also a .wizard-card,
   but not every .wizard-card is a step - this compound selector keeps the
   refresh scoped to the wizard without touching the shared card look used
   on auth/dashboard/admin) get a slightly larger, more elevated treatment
   plus a thin brand-gradient cap and a soft entrance each time goToStep()
   toggles display, so moving between steps feels like a real transition
   instead of a hard cut. */
.wizard-card.step {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 40px;
}
/* This was a brand gradient cap; flattening it left a 4px amber bar across the
   top of every step. Amber means "we could not verify this, check it yourself"
   in this palette, so a permanent one on every screen says something untrue —
   and the green progress rail directly above it already marks position in the
   flow. The card's own edge is enough. */
/* The step entrance used to be a CSS @keyframes animation here, but a
   finished animation held via fill-mode:both resolves `transform` to a
   matrix rather than the literal `none` keyword - and an element with a
   resolved transform becomes the containing block for any descendant's
   position:fixed, which silently re-anchored the mobile sticky action bar to
   the card instead of the viewport. It's now driven by a spring in
   wizard.js's enterStepCard(), which explicitly sets transform to the literal
   `none` once settled - fixing the bug at the root instead of cleaning it up
   after the fact with an animationend listener. See spring.js/wizard.js. */
@media (max-width: 480px) {
  .wizard-card.step { padding: 28px 22px; }
}

.wizard-card h2 { color: var(--kadia-navy); margin-top: 0; }
.wizard-card p.hint { color: var(--kadia-text-muted); margin-top: -8px; margin-bottom: 22px; }
.wizard-card.step h2 { font-size: 1.65rem; font-weight: 800; margin-bottom: 10px; }
.wizard-card.step p.hint { font-size: 1rem; line-height: 1.65; margin-bottom: 30px; }

/* a field the vision model came back null for - distinct from .field-invalid
   (red, user's own mistake) since this isn't something the user did wrong,
   just a gap the OCR left for them to fill in themselves */
.field-ocr-missed input, .field-ocr-missed select { border-color: #e3a24d; background: #fffaf3; }
.field p.field-hint-missed { margin: 6px 0 0; color: #8a4a12; font-weight: 600; font-size: .85rem; }

.field { margin-bottom: 18px; }
.field label { display: block; font-weight: 700; margin-bottom: 8px; color: var(--kadia-navy); }
.field input[type=text],
.field input[type=number],
.field input[type=tel],
.field input[type=password],
.field input[type=date],
.field input[type=email],
.field select,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1.5px solid var(--kadia-border);
  font-family: inherit;
  font-size: 1rem;
  background: #fff;
  color: var(--kadia-text);
}
.field textarea { min-height: 90px; resize: vertical; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px; border-color: var(--kadia-teal-light);
}

/* wizard-only field refinement (scoped via the .step ancestor - every
   wizard step card carries this class, auth/admin/dashboard forms don't -
   see .wizard-card.step above for why this scoping pattern is used
   throughout this file instead of touching the shared .field rules). */
.step .field input[type=text], .step .field input[type=number], .step .field input[type=tel],
.step .field input[type=password], .step .field input[type=date], .step .field input[type=email],
.step .field select, .step .field textarea {
  border-radius: 12px;
  padding: 13px 15px;
  border: 1.5px solid var(--kadia-border);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.step .field input:focus, .step .field select:focus, .step .field textarea:focus {
  border-color: var(--kadia-teal);
  box-shadow: 0 0 0 4px var(--kadia-teal-tint);
}

/* choice tiles (violation type, etc.) - a fixed min-height with centered
   content keeps every tile in a row the same height regardless of how many
   lines its own label wraps to (Arabic/Hebrew labels differ a lot in
   length), which is what made this grid look jagged and cramped before -
   the uneven row heights were doing a lot of the "this looks unpolished"
   work on their own, independent of padding/font size. */
.option-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
/* .option-pill and .method-card (below) are real <button role="radio">
   elements now, not <div>s - a keyboard/screen-reader user could not select
   a violation type or a delivery method at all before that, a real bug
   found in a live accessibility audit. font/color/appearance resets here
   undo the browser's own button styling so they still look identical to
   the plain divs they replaced. */
.option-pill, .method-card {
  font: inherit; color: inherit; text-align: inherit; appearance: none; -webkit-appearance: none;
  width: 100%; display: block;
}
.option-pill:focus-visible, .method-card:focus-visible {
  outline: 2px solid var(--kadia-teal); outline-offset: 2px;
}
.option-pill {
  min-height: 92px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  border: 1.5px solid var(--kadia-border);
  border-radius: var(--r-card);
  padding: 16px 16px;
  text-align: center;
  cursor: pointer;
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.4;
  background: #fff;
  box-shadow: 0 1px 2px rgba(19, 23, 26, .03);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease;
}
.option-pill:hover { border-color: var(--kadia-teal-light); transform: translateY(-2px); box-shadow: 0 8px 18px rgba(19, 23, 26, .08); }
.option-pill .pill-ico { transition: transform .2s var(--ease); }
.option-pill:hover .pill-ico { transform: scale(1.1) rotate(-4deg); }
.option-pill.selected {
  position: relative;
  border-color: var(--kadia-teal);
  background: var(--kadia-teal-tint);
  color: var(--kadia-teal-dark);
  box-shadow: 0 6px 18px rgba(15, 122, 69, .2);
}
.option-pill.selected .pill-ico { transform: scale(1.1); }
.option-pill.selected::after {
  content: "✓";
  position: absolute; top: 10px; inset-inline-end: 10px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--kadia-teal); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: .66rem; font-weight: 900;
}
@media (max-width: 480px) {
  .option-grid { grid-template-columns: repeat(2, 1fr); }
  .option-pill { min-height: 80px; font-size: .95rem; padding: 14px 10px; }
}
/* A quick staggered pop-in when the grid first renders, not a permanent
   loop - a picker you stare at while deciding shouldn't keep moving. */
@media (prefers-reduced-motion: no-preference) {
  .option-grid .option-pill {
    animation: kadia-tile-pop .38s var(--ease) both;
    animation-delay: calc(var(--tile-i, 0) * 45ms);
  }
}
@keyframes kadia-tile-pop {
  from { opacity: 0; transform: translateY(10px) scale(.92); }
  to { opacity: 1; transform: none; }
}

/* ---------- step 1: scan (sub-screen A) -> confirm details (sub-screen B) ---------- */
.step1-subnav { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; }
.step1-subdot {
  flex: none; width: 26px; height: 26px; border-radius: var(--r-plate);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-sm); font-weight: 700;
  border: 1px solid var(--rule); background: transparent;
  color: var(--ink-3);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.step1-subdot.active { border-color: var(--ink); background: var(--ink); color: var(--paper); }
.step1-subdot.done { border-color: var(--signal); background: var(--signal-tint); color: var(--kadia-teal-deep); }
.step1-subdot-label { font-size: var(--t-sm); font-weight: 500; color: var(--ink-3); transition: color var(--dur) var(--ease); }
.step1-subdot-label.active { color: var(--ink); font-weight: 600; }
.step1-subdot-line { flex: 1; height: 1px; background: var(--rule); min-width: 16px; max-width: 40px; }
@media (max-width: 480px) { .step1-subdot-label { display: none; } }

/* the one legal warning that actually matters most in the whole wizard
   (paying the ticket forfeits the appeal right) - gets its own distinct,
   gently-glowing treatment instead of blending into a generic muted alert
   box, so it reads as "stop and notice this" without being alarmist. */
.legal-alert {
  display: flex; align-items: flex-start; gap: 13px;
  background: var(--stop-tint);
  border: 1px solid var(--stop);
  border-radius: var(--r-plate);
  padding: 14px 16px;
  margin-bottom: 20px;
}
.legal-alert-icon {
  flex: none;
  width: 22px; height: 22px;
  margin-top: 1px;
  color: var(--stop);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem;
}
.legal-alert-text {
  margin: 0; color: #7d221c; font-size: var(--t-md); line-height: 1.6; font-weight: 500;
}
.legal-alert-text strong { color: var(--stop); font-weight: 700; }
/* The deadline note (deadlines.py) while there is still comfortable time:
   same layout, calm colors. Red stays reserved for "act now" - under 7 days,
   or already past - so it keeps meaning something. */
.legal-alert.is-calm { background: var(--signal-tint); border-color: var(--signal); }
.legal-alert.is-calm .legal-alert-icon { color: var(--signal); }
.legal-alert.is-calm .legal-alert-text,
.legal-alert.is-calm .legal-alert-text strong { color: var(--kadia-teal-deep); }

/* Extraction-failed notice: same layout language as .legal-alert, but
   caution amber ("we couldn't verify this, check it yourself") rather than
   stop red ("money/deadline") - this is a request for a second look, not an
   urgent warning. Applied only when the scan found nothing at all; a
   partial miss (some fields read, some didn't) stays as the plain hint
   text it already was, since that case isn't a failure. */
.ocr-fail-note {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--caution-tint);
  border: 1px solid var(--caution);
  border-radius: var(--r-plate);
  padding: 12px 14px;
  margin: 0 !important;
  color: #6b3610; font-weight: 500; line-height: 1.55;
}
.ocr-fail-note::before {
  content: "";
  flex: none; width: 20px; height: 20px; margin-top: 1px;
  background-color: var(--caution);
  -webkit-mask: var(--i-alert) center / contain no-repeat;
          mask: var(--i-alert) center / contain no-repeat;
}

/* personal-area ("my tickets") promo banner - only ever shown to a
   logged-in user who actually still has an unused launch-promo credit (see
   dashboard.js's renderPromoBanner), so unlike the landing-page strip this
   one is personal ("you have one waiting") rather than a general
   announcement. Whole thing is a single <a> so the entire row is one big
   tap target into the wizard. */
.dash-promo-banner {
  display: flex; align-items: center; gap: 14px;
  background: var(--caution-tint);
  border: 1px solid var(--caution);
  border-radius: var(--r-card);
  padding: 16px 20px;
  margin-bottom: 22px;
  transition: box-shadow .15s ease;
}
.dash-promo-banner:hover { box-shadow: 0 4px 14px rgba(180, 83, 26, .14); }
.dash-promo-icon {
  flex: none; width: 38px; height: 38px; border-radius: var(--r-plate);
  border: 1px solid var(--caution);
  background: #fff;
  color: var(--caution);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem;
}
.dash-promo-text { flex: 1; min-width: 0; color: #6b3610; font-weight: 700; font-size: .95rem; line-height: 1.5; }
.dash-promo-cta {
  flex: none; color: var(--caution); font-weight: 800; font-size: .88rem;
  white-space: nowrap;
}
@media (max-width: 560px) {
  .dash-promo-banner { flex-wrap: wrap; }
  .dash-promo-cta { width: 100%; padding-inline-start: 54px; }
}

/* dashboard "personal area" summary - a dark ink-surface card above the
   ticket list, reusing the --ink/--on-ink pair the report itself uses for
   verdict bars rather than inventing a separate dark palette: a quick,
   always-visible read on "how many tickets, how many need me to do
   something" before scrolling into the list. Only rendered once there is
   at least one ticket (renderDashHero in dashboard.js) - the existing
   empty state already carries that message better than four zeroes would. */
.dash-hero {
  background: var(--ink);
  color: var(--on-ink);
  border-radius: var(--r-card);
  padding: 26px 28px;
  margin-bottom: 22px;
}
.dash-hero-eyebrow {
  display: block; font-size: var(--t-xs); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--on-ink-dim); margin-bottom: 6px;
}
.dash-hero-title { margin: 0 0 20px; font-size: var(--t-xl); font-weight: 800; color: var(--on-ink); }
.dash-hero-stats { display: flex; flex-wrap: wrap; gap: 10px; }
.dash-hero-stat {
  flex: 1 1 110px;
  border-inline-start: 1px solid var(--rule-on-ink);
  padding-inline-start: 16px;
}
.dash-hero-stat:first-child { border-inline-start: none; padding-inline-start: 0; }
.dash-hero-num {
  display: block; font-size: var(--t-2xl); font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--on-ink);
}
/* urgent (due soon) leans on the existing gold - not --stop, which is tuned
   for text on --paper and loses contrast on --ink; positive (submitted)
   reuses --signal-bright, already documented as the ink-surface signal. */
.dash-hero-stat.urgent .dash-hero-num { color: var(--kadia-gold-light); }
.dash-hero-stat.positive .dash-hero-num { color: var(--signal-bright); }
.dash-hero-label { display: block; margin-top: 4px; font-size: var(--t-sm); color: var(--on-ink-dim); }
@media (max-width: 560px) {
  .dash-hero { padding: 22px 20px; }
  .dash-hero-stats { gap: 16px 0; }
  .dash-hero-stat { flex: 1 1 45%; border-inline-start: none; padding-inline-start: 0; }
}

.step1-scan-actions { display: flex; flex-direction: column; align-items: center; gap: 14px; margin-top: 22px; }

/* desktop-only split: dropzone left, "what happens next" panel right - fills
   the extra width a wide viewport gives the wizard instead of leaving a
   phone-width card floating in a sea of empty gray. See showStep1Sub() in
   wizard.js, which toggles .wizard-shell-wide only while this sub-screen is
   showing (the chat/payment steps stay at the narrower reading width). */
.step1-scan-explainer { display: none; }
@media (min-width: 900px) {
  .wizard-shell.wizard-shell-wide { max-width: 1000px; }
  .step1-scan-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }
  .step1-scan-explainer {
    display: flex; flex-direction: column; gap: 18px; padding-top: 4px;
  }
  .step1-scan-explainer h3 {
    font-size: 1.05rem; font-weight: 800; color: var(--kadia-navy); margin: 0;
  }
  .step1-scan-explainer .mini-step-row { display: flex; gap: 12px; align-items: flex-start; }
  .step1-scan-explainer .dot-num {
    flex: none; width: 26px; height: 26px; border-radius: 50%;
    background: var(--kadia-teal-tint); color: var(--kadia-teal-deep, var(--kadia-teal-dark));
    font-size: .8rem; font-weight: 800;
    display: flex; align-items: center; justify-content: center;
  }
  .step1-scan-explainer p { margin: 0; font-size: .92rem; line-height: 1.65; color: var(--kadia-text-muted); }
  .step1-scan-explainer p b { color: var(--kadia-text); }
}
.step1-scan-continue { width: 100%; max-width: 320px; }

.step1-back-link {
  background: none; border: none; cursor: pointer; padding: 0;
  font-weight: 700; font-size: .88rem; color: var(--kadia-text-muted);
  margin-bottom: 14px; display: inline-flex; align-items: center; gap: 4px;
}
.step1-back-link:hover { color: var(--kadia-teal-dark); }

.step1-photo-summary {
  display: flex; align-items: center; gap: 14px;
  background: var(--kadia-teal-tint); border-radius: 14px; padding: 12px 16px; margin-bottom: 26px;
}
.step1-photo-summary img {
  width: 56px; height: 56px; border-radius: 10px; object-fit: cover; flex: none;
  box-shadow: 0 2px 8px rgba(0,0,0,.12);
}
.step1-photo-summary p.hint { color: var(--kadia-teal-dark); font-weight: 700; }

.field-group { margin-bottom: 46px; }
.field-group:last-of-type { margin-bottom: 0; }
.field-group-title {
  display: flex; align-items: center; gap: 11px;
  font-size: 1.05rem; font-weight: 800; color: var(--kadia-navy);
  margin-bottom: 24px;
}
.field-group-title::before {
  content: ""; flex: none; width: 5px; height: 22px; border-radius: 3px;
  background: var(--caution);
}

.scan-field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 26px; }
.scan-field-grid .field-span-2 { grid-column: 1 / -1; }
@media (max-width: 600px) { .scan-field-grid { grid-template-columns: 1fr; } }

/* wizard-only field rhythm (scoped via .step, same pattern as the input
   radius/focus rules above) - noticeably more breathing room between
   fields/labels than the shared default, which is tuned tighter for dense
   admin/auth forms. */
.step .field { margin-bottom: 24px; }
.step .field label { font-size: .95rem; margin-bottom: 9px; }
.step .field p.hint { font-size: var(--t-sm); color: var(--ink-3); }

/* the fields the AI already read for you get a small green check (the exact
   "just finished" pop already used when the scan itself completes, see
   .scan-spinner.done) - closing the loop between the landing page's promise
   and this screen actually delivering it. the ones it missed get an amber
   pencil instead of the same green, not just a re-tinted checkmark, so "we
   found this" and "please write this" read as different at a glance. */
.field-status-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; font-size: .66rem; font-weight: 900;
  vertical-align: middle; margin-inline-start: 3px;
}
.field-status-badge:empty { display: none; }
.field-status-badge.ok {
  background: var(--kadia-teal-tint); color: var(--kadia-teal-dark);
  animation: kadia-check-pop .45s cubic-bezier(.34,1.56,.64,1);
}
.field-status-badge.missed { background: #fdf0dc; color: #b26a12; }
@media (prefers-reduced-motion: reduce) {
  .field-status-badge.ok { animation: none; }
}

.wizard-actions { display: flex; justify-content: space-between; margin-top: 26px; }

/* the wizard's two committing actions (pay, and the questionnaire's
   "check my grounds") get the same teal-deep gradient the homepage uses for
   its primary CTAs, so the moment of commitment looks the same everywhere */
#payButton, #toStep3, #toStep4 { background: var(--signal); box-shadow: none; }
#payButton { padding-block: 16px; font-size: 1.05rem; }
#toStep4 { padding: 15px 34px; font-size: 1.02rem; }
#payButton:hover, #toStep3:hover, #toStep4:hover { background: var(--kadia-teal-dark); }

/* Sticky bottom primary-action button (mobile only) - opt-in via this class
   on a single primary CTA button (not the back/next pairs), so the step's
   main forward action stays reachable with the thumb.

   This used to be an inset pill at left:92px, physical rather than logical,
   specifically to clear the floating accessibility button in the bottom-left
   corner. It is now a full-width action bar instead, which is what a native
   app puts there, and the floating buttons were moved ABOVE it - so the
   physical-offset workaround is no longer needed and the bar can use logical
   insets like everything else. See the app-shell block for the new rule. */
@media (max-width: 767px) {
  .wizard-shell { padding-bottom: 0; }
}

.upload-box {
  position: relative;
  border: 2px dashed var(--rule);
  border-radius: 18px;
  padding: 0;
  text-align: center;
  cursor: pointer;
  color: var(--kadia-text-muted);
  display: block;
  overflow: hidden;
  background: var(--kadia-bg);
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
}
.upload-box:hover { border-color: var(--kadia-teal-light); background: var(--kadia-teal-tint); transform: translateY(-1px); }

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 34px 22px;
  min-height: 140px;
}
.upload-icon { font-size: 2.1rem; margin-bottom: 6px; color: var(--signal); }
.upload-title { font-weight: 600; color: var(--ink); font-size: var(--t-lg); }
.upload-sub { font-size: var(--t-sm); color: var(--ink-3); max-width: 34ch; }

/* upload scanning state: keeps the customer's actual photo clearly visible
   (no full-image tint wash) and dramatizes real OCR work with a scanner-bar
   sweep + soft trailing glow, viewfinder corners, and a proper checkmark
   pop on completion - the same "scan then confirm" motion language as the
   landing-page hero, so the product feels like one system throughout. */
.upload-preview { position: relative; line-height: 0; min-height: 220px; background: var(--kadia-bg); border-radius: var(--r-card-sm); overflow: hidden; }
.upload-preview img {
  width: 100%; height: 220px; max-height: 320px; object-fit: cover; display: block; border-radius: var(--r-card-sm);
  filter: brightness(1) saturate(1); transition: filter .4s ease;
}
.upload-preview.scanning img { filter: brightness(.95) saturate(1.05); }

.scan-corner {
  --vf-corner-size: 28px;
  --vf-corner-color: var(--kadia-teal-light);
  opacity: 0; transition: opacity .25s ease, border-color .25s ease, filter .25s ease;
  z-index: 3;
}
.upload-preview.scanning .scan-corner, .upload-preview.done .scan-corner { opacity: 1; }
.upload-preview.scanning .scan-corner { filter: drop-shadow(0 0 5px rgba(34, 192, 122, .55)); }
.scan-corner.tl { top: 12px; inset-inline-start: 12px; border-inline-end: none; border-bottom: none; }
.scan-corner.tr { top: 12px; inset-inline-end: 12px; border-inline-start: none; border-bottom: none; }
.scan-corner.bl { bottom: 12px; inset-inline-start: 12px; border-inline-end: none; border-top: none; }
.scan-corner.br { bottom: 12px; inset-inline-end: 12px; border-inline-start: none; border-top: none; }
.upload-preview.done .scan-corner { border-color: var(--kadia-success); filter: none; }

.scan-line {
  position: absolute; inset-inline: 5%; height: 3px; top: 4%;
  background: var(--signal);
  box-shadow: 0 0 14px 3px rgba(34, 192, 122, .7), 0 0 34px 8px rgba(15, 122, 69, .25);
  opacity: 0; z-index: 2; border-radius: 2px;
}
.scan-line::after {
  content: ""; position: absolute; inset-inline: 0; top: 3px; height: 46px;
  background: var(--signal);
}
.upload-preview.scanning .scan-line { opacity: 1; animation: kadia-scan-sweep 2.1s cubic-bezier(.45,0,.55,1) infinite; }
@keyframes kadia-scan-sweep { 0% { top: 4%; } 50% { top: 92%; } 100% { top: 4%; } }

.upload-status {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px; max-width: 90%;
  background: rgba(36, 26, 51, .82); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  color: #fff; padding: 8px 16px; border-radius: var(--r-plate); font-size: 0.85rem; font-weight: 700;
  z-index: 4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: kadia-fade-up 0.3s ease-out;
  transition: background .3s ease;
}
.upload-preview.done .upload-status {
  background: rgba(30, 138, 95, .92);
  animation: kadia-status-pop .4s cubic-bezier(.34,1.56,.64,1);
}
@keyframes kadia-status-pop {
  0% { transform: translateX(-50%) scale(.9); }
  55% { transform: translateX(-50%) scale(1.05); }
  100% { transform: translateX(-50%) scale(1); }
}

.scan-spinner {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px;
  border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff;
  border-radius: 50%; animation: spin 0.8s linear infinite;
}
.scan-spinner.done {
  border: none; animation: kadia-check-pop .45s cubic-bezier(.34,1.56,.64,1);
}
.scan-spinner.done::after { content: "✓"; color: #fff; font-size: 12px; font-weight: 900; line-height: 1; }
@keyframes kadia-check-pop {
  0% { transform: scale(.2); opacity: 0; }
  65% { transform: scale(1.3); opacity: 1; }
  100% { transform: scale(1); }
}

/* each matched ground is a small verdict card: a teal marker rail on the RTL
   start edge plus a success check, so a list of grounds reads as findings in
   the customer's favour rather than as generic beige note boxes */
.ground-result {
  position: relative;
  border: 1px solid var(--kadia-border);
  border-radius: var(--r-card);
  padding: 18px 20px;
  padding-inline-start: 54px;
  margin-bottom: 12px;
  background: var(--kadia-card);
  box-shadow: 0 2px 8px rgba(19, 23, 26, .04);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.ground-result::before {
  content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; width: 4px;
  border-start-start-radius: 16px; border-end-start-radius: 16px;
  background: var(--signal);
}
.ground-result::after {
  content: "✓";
  position: absolute; top: 18px; inset-inline-start: 18px;
  width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--kadia-success-tint, var(--signal-tint)); color: var(--kadia-success);
  font-size: .72rem; font-weight: 900;
}
.ground-result:hover { border-color: var(--kadia-teal-light); box-shadow: 0 8px 20px rgba(19, 23, 26, .08); }
.ground-result h4 { margin: 0; color: var(--kadia-navy); font-size: 1.02rem; line-height: 1.55; }
.ground-result .legal { color: var(--kadia-text-muted); font-size: 0.9rem; line-height: 1.6; margin-top: 10px; border-top: 1px dashed var(--kadia-border); padding-top: 10px; }
.tag {
  display: inline-block; margin-bottom: 8px;
  background: var(--kadia-teal-tint);
  color: var(--kadia-teal-deep, var(--kadia-teal-dark));
  font-size: 0.72rem; font-weight: 800; letter-spacing: .03em;
  padding: 4px 11px; border-radius: var(--r-plate);
}

.letter-preview {
  direction: rtl;
  text-align: right;
  white-space: pre-wrap;
  font-family: 'Tajawal', 'Segoe UI', sans-serif;
  background: #fefdfb;
  border: 1px solid var(--kadia-border);
  border-radius: 14px;
  padding: 26px 24px;
  line-height: 1.9;
  min-height: 300px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 1px 3px rgba(19, 23, 26, .04);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.letter-preview:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px; border-color: var(--kadia-teal);
  box-shadow: 0 0 0 4px var(--kadia-teal-tint);
}

/* letter-document: a print-ready rendering of the same letter text, hidden
   on screen and revealed only for window.print() via the @media print rule
   below - so printing/saving-as-PDF produces a proper letterhead document
   (logo, firm name, brand rule, footer contact) instead of a plain
   textarea dump. Kept deliberately restrained - this is a formal letter
   submitted to a government office, not a marketing page, so the brand
   shows up as a letterhead mark and a thin accent rule, not color everywhere.
   Pagination is guarded (orphans/widows + page-break-inside) so a stray
   line or the footer never strands alone on an otherwise-blank page. */
.letter-document { display: none; }

.letter-document-header {
  margin-bottom: 26px;
  page-break-inside: avoid;
  page-break-after: avoid;
}
.letter-document-brandrow { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.letter-document-logo { width: 52px; height: 52px; flex: none; }

/* diagonal, low-opacity repeating "KADIA" watermark across every printed/
   PDF page. A first attempt used a position:fixed text element, which
   turned out to not print at all - confirmed via a real saved PDF, empty
   where the watermark should have been. Chrome's print/PDF renderer has a
   long-documented limitation with position:fixed content (it's reliably
   supported for screen media, not print). A tiled background-image on
   .letter-document itself sidesteps that entirely: backgrounds paint
   continuously across a box's full height regardless of where print
   pagination slices it into pages, so this needs no per-page positioning
   trick at all. -webkit-print-color-adjust:exact (see @media print above)
   is what stops the browser from silently dropping it as "just decoration". */
@media print {
  .letter-document {
    background-repeat: repeat;
    background-size: 240px 170px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='170'><text x='120' y='90' font-family='Arial, sans-serif' font-size='26' font-weight='800' fill='rgba(19, 23, 26,0.07)' text-anchor='middle' transform='rotate(-32 120 90)'>KADIA</text></svg>");
  }
}
.letter-document-firm { line-height: 1.4; }
.letter-document-header .firm-name {
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--kadia-navy);
  letter-spacing: 0.01em;
}
.letter-document-header .firm-meta {
  font-size: 0.8rem;
  color: #6b6178;
  margin-top: 3px;
  letter-spacing: 0.02em;
}
/* hairline + a short two-tone accent tick, aligned to the RTL start -
   a letterhead mark, not a webpage banner */
.letter-document-rule {
  position: relative;
  height: 1px;
  background: var(--rule);
}
.letter-document-rule::after {
  content: "";
  position: absolute;
  top: -1.5px;
  right: 0;
  width: 44px;
  height: 3px;
  border-radius: 2px;
  background: var(--ink);
}

.letter-document-body {
  direction: rtl;
  text-align: right;
  white-space: pre-wrap;
  font-family: 'Segoe UI', Tahoma, Arial, sans-serif;
  line-height: 1.9;
  font-size: 0.99rem;
  color: #1c1c1c;
  orphans: 3;
  widows: 3;
}

.letter-document-footer {
  position: relative;
  margin-top: 34px;
  padding-top: 16px;
  text-align: center;
  font-size: 0.78rem;
  color: #8a8296;
  letter-spacing: 0.01em;
  page-break-inside: avoid;
}
.letter-document-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 60px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  opacity: 0.55;
}

@page {
  margin: 20mm 18mm;
}
@media print {
  html, body { background: #fff; }
  html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  body * { visibility: hidden; }
  .letter-document, .letter-document * { visibility: visible; }
  .letter-document {
    display: block;
    position: absolute;
    top: 0; right: 0; left: 0;
    padding: 0;
  }
}

.method-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
/* zero-grounds tickets only ever offer the document-only card (see wizard.js's
   toStep4 handler) - a 3-column grid with two hidden siblings leaves it
   stranded in the first third of the row, so collapse to one narrow column. */
.method-choice.single-option { grid-template-columns: 1fr; max-width: 360px; }
/* the reserved 44px header strip is what lets the promo ribbon and the
   selected-check share the card's top edge without either being clipped by
   the grid gap the way the old top:-12px hanging ribbon was */
.method-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 4px;
  background: var(--plate);
  border: 1.5px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 44px 18px 18px;
  cursor: pointer;
  text-align: start;
  transition: border-color .15s ease, background .15s ease;
}
.method-card:hover { border-color: var(--signal); }
/* a full-width band across the card's top edge, not a floating pill: the
   label is long ("free - launch offer") and on a narrow card a pill collided
   with the selected-check in the opposite corner */
.promo-free-ribbon {
  position: absolute; top: 0; inset-inline: 0;
  background: var(--caution);
  color: #fff;
  padding: 6px 12px;
  text-align: center;
  font-weight: 800; font-size: .74rem; line-height: 1.35;
}
/* with the band present the check drops beneath it, and the card gains the
   band's height back as padding so the price never sits under it */
.method-card.has-ribbon { padding-top: 62px; }
.method-card.has-ribbon.selected { padding-top: 61px; }
.method-card.has-ribbon.selected::after { top: 34px; }
.method-card.has-ribbon.selected::before { display: none; }
/* Selection reads as a tinted field with a signal border, not a solid fill:
   the card's own price and description stay dark text on light ground. */
.method-card.selected {
  border: 2px solid var(--signal);
  padding: 43px 17px 17px;
  background: var(--signal-tint);
  box-shadow: none;
}
/* same gradient cap as the recommended pricing tier on the homepage - the
   "this is the chosen one" signal is the same shape across the whole site */
.method-card.selected::before {
  content: ""; position: absolute; top: 0; inset-inline: 0; height: 5px;
  background: var(--signal);
}
/* the selected-tier mark: drawn, like every other confirmation in the system */
.method-card.selected::after {
  content: "";
  position: absolute; top: 12px; inset-inline-end: 12px;
  width: 22px; height: 22px;
  background-color: var(--signal);
  -webkit-mask: var(--i-check-ring) center / contain no-repeat;
          mask: var(--i-check-ring) center / contain no-repeat;
  box-shadow: none;
}
.method-card .amt { font-size: 1.55rem; font-weight: 800; color: var(--kadia-navy); line-height: 1.2; }
.method-card.selected .amt { color: var(--kadia-teal-deep, var(--kadia-teal-dark)); }
/* a locked card must still be readable: the old blanket opacity:.65 dropped
   the price and description below AA. Dashed border + tinted ground carries
   "not available yet" without dimming the text. */
.method-card.locked {
  background: var(--kadia-bg);
  border-style: dashed;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.method-card.locked .amt { color: var(--kadia-text-muted); }
.method-card.locked:hover { background: var(--kadia-bg-dim, var(--kadia-bg)); }
.method-card .lock-note { color: var(--kadia-gold-text, var(--kadia-gold)); font-size: 0.78rem; font-weight: 700; margin-top: 8px; }
.method-card.locked.unlock-nudge { animation: kadia-unlock-nudge .5s ease; }
@keyframes kadia-unlock-nudge {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

/* registered-mail add-on row: a checkbox, not a third method-card - see the
   comment above #mailAddonRow in app.html for why. Sits right under the
   digital card, shown only when that card is selected and unlocked. */
.mail-addon-toggle {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 20px;
  padding: 14px 16px;
  border: 1.5px dashed var(--kadia-border);
  border-radius: var(--r-field);
  cursor: pointer;
  background: var(--kadia-bg);
  transition: border-color .15s ease, background .15s ease;
}
.mail-addon-toggle:hover { border-color: var(--signal); }
.mail-addon-toggle input[type="checkbox"] { width: 20px; height: 20px; flex: none; accent-color: var(--signal); }
.mail-addon-copy { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.mail-addon-title { font-weight: 700; color: var(--kadia-navy); }
.mail-addon-desc { font-size: .82rem; color: var(--kadia-text-muted); }
.mail-addon-price { font-weight: 800; color: var(--kadia-teal-deep, var(--kadia-teal-dark)); flex: none; }
.mail-addon-toggle.checked { border-style: solid; border-color: var(--signal); background: var(--signal-tint); }

/* guest -> account unlock panel (step 4): a positive "unlock" invitation,
   not a dead-end error - appears in place when a guest reaches for a
   locked option, pre-fills what they already typed, and never navigates
   away from the wizard so nothing already entered is lost. */
/* lighter than the old full teal wash: a plain white card matching the
   wizard/auth card grammar, with a single teal accent bar at the top so it
   still reads as an invitation rather than a warning box */
.unlock-panel {
  position: relative; overflow: hidden;
  background: var(--kadia-card);
  border: 1px solid var(--kadia-border);
  border-radius: 20px;
  box-shadow: var(--shadow);
  padding: 26px 22px 22px;
  margin-bottom: 20px;
}
.unlock-panel::before {
  content: ""; position: absolute; top: 0; inset-inline: 0; height: 4px;
  background: var(--signal);
}
.unlock-panel-header { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 18px; }
.unlock-icon {
  flex: none; width: 44px; height: 44px; border-radius: 14px;
  background: var(--kadia-teal-tint);
  color: var(--kadia-teal-deep, var(--kadia-teal-dark));
  display: flex; align-items: center; justify-content: center; font-size: 1.15rem;
}
.unlock-icon svg { display: block; }
.unlock-panel #unlockRegisterBtn, .unlock-panel #unlockLoginBtn {
  background: var(--signal);
  box-shadow: none;
}
.unlock-panel-header h3 { margin: 0 0 4px; color: var(--kadia-navy); font-size: 1.05rem; }
.unlock-panel-header p { margin: 0; color: var(--kadia-text-muted); font-size: .88rem; line-height: 1.6; }
.unlock-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 600px) { .unlock-field-row { grid-template-columns: 1fr; } }
.unlock-switch-link { text-align: center; margin: 12px 0 0; font-size: .88rem; color: var(--kadia-text-muted); }

.alert {
  padding: 14px 16px;
  border-radius: 10px;
  margin-bottom: 16px;
  font-weight: 600;
}
.alert-error { background: #fdecea; color: var(--kadia-danger); }
.alert-success { background: #eaf7f0; color: var(--kadia-success); }
.alert-info { background: #eaf4f7; color: var(--kadia-teal); }
.alert-warning { background: #fdf2e9; color: #8a4a12; border: 1.5px solid #f0c896; line-height: 1.7; }
.alert-warning strong { color: #6b3a0e; }

.spinner {
  display: inline-block; width: 18px; height: 18px;
  border: 3px solid rgba(255,255,255,0.4); border-top-color: #fff;
  border-radius: 50%; animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- step 5 / other-report confirmation ---------- */
/* the final screen was a left-aligned green <h2> with a text checkmark glued
   to the copy; it now gets a real success mark and a centred, calm layout -
   this is the last thing a paying customer sees. */
.done-block { text-align: center; padding: 8px 0 4px; max-width: 520px; margin: 0 auto; }
.done-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 74px; height: 74px; border-radius: 50%;
  margin-bottom: 18px;
  background: var(--signal-tint);
  border: 1px solid var(--signal);
  color: var(--signal);
  box-shadow: none;
  animation: kadia-pop-in .55s cubic-bezier(.34,1.56,.64,1) both;
}
.done-mark svg { display: block; }
.done-block h2 { color: var(--kadia-success); margin: 0 0 12px; font-size: 1.55rem; }
.done-block > p { color: var(--kadia-text-muted); line-height: 1.8; margin: 0 0 18px; }
.done-block .done-vault-hint { font-size: .92rem; margin-top: 20px; }
.done-block .btn { margin-top: 4px; }

.track-box {
  background: var(--ink);
  color: #fff;
  border-radius: 18px;
  padding: 22px;
  text-align: center;
  margin: 6px 0 4px;
  box-shadow: var(--shadow-lg);
}
.track-box .num { font-size: 1.6rem; font-weight: 800; color: var(--kadia-gold-light); letter-spacing: 1px; margin: 10px 0 0; }

/* ---------- analyzing / result (step 3) ---------- */
/* The signature moment of this direction. The old version span a ring behind a
   scales emoji while a checklist claimed work was happening. Here the work IS
   the interface: the same report component as the home page, running its
   checkpoints, then handing down a verdict. */
@keyframes kadia-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.analyzing-wrap { padding: 8px 0 4px; }
.analyzing-title {
  color: var(--ink); margin-bottom: 6px;
  font-size: var(--t-2xl); letter-spacing: -.02em;
}
.analyzing-sub { color: var(--ink-2); font-size: var(--t-md); margin-bottom: 24px; max-width: 52ch; }
.analyzing-note {
  margin-top: 16px; font-size: var(--t-sm); color: var(--ink-3);
  display: flex; align-items: center; gap: 8px;
}

/* the live report: rows are dim until wizard.js marks them .active */
.report-live { margin: 0; }
.analyzing-checklist { list-style: none; padding: 0; margin: 0; }
.analyzing-checklist li {
  display: flex; align-items: center; gap: 11px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-md); font-weight: 500;
  color: #9aa39c;
}
.analyzing-checklist li:last-child { border-bottom: 0; }
.analyzing-checklist li .dot {
  flex: none; width: 18px; height: 18px;
  background-color: #c2c8c2;
  -webkit-mask: var(--i-dash) center / contain no-repeat;
          mask: var(--i-dash) center / contain no-repeat;
}
.analyzing-checklist li.active { color: var(--ink); }
.analyzing-checklist li.active .dot {
  background-color: var(--signal);
  -webkit-mask-image: var(--i-check-ring);
          mask-image: var(--i-check-ring);
}
/* the row's opacity/position pop and the dot's overshoot scale are spring-
   driven from wizard.js's activateChecklistRow() now, not CSS @keyframes -
   only the plain color crossfades stay here. */
@media (prefers-reduced-motion: no-preference) {
  .analyzing-checklist li { transition: color .22s var(--ease); }
  .analyzing-checklist li .dot { transition: background-color .22s var(--ease); }
}

/* ---------- the verdict ---------- */
.result-badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px;
  border: 1px solid var(--signal);
  border-radius: var(--r-plate);
  background: var(--signal-tint);
  color: var(--kadia-teal-deep);
  font-weight: 600; font-size: var(--t-sm);
  letter-spacing: .02em;
  margin-bottom: 18px;
}
.result-title {
  color: var(--ink); margin-bottom: 8px;
  font-size: var(--t-2xl); letter-spacing: -.02em;
  max-width: 24ch;
}
.result-subtitle {
  color: var(--ink-2); margin: 0 0 28px;
  max-width: 52ch; line-height: 1.7; font-size: var(--t-md);
}

/* The count is the finding, so it gets the loudest treatment on the page: a
   white numeral ring on a soft stop-red card. Red here isn't "danger to the
   reader" - it's "look here first", the same urgency register as the
   late-payment note below it. Kept to white-on-red / red-on-white pairings
   only (never red-on-red) after an earlier version put deep green numerals
   on a green circle and measured 1.9:1 contrast. */
.result-number-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  text-align: center;
  background: var(--stop-tint);
  border: 1px solid var(--stop);
  border-radius: var(--r-plate);
  padding: 24px 22px;
  margin-bottom: 28px;
}
.result-number-ring {
  flex: none;
  width: 86px; height: 86px;
  border-radius: 50%;
  border: 3px solid var(--stop);
  background: #fff;
  display: flex; align-items: center; justify-content: center;
}
.result-number {
  font-size: 2.5rem; font-weight: 800; line-height: 1;
  letter-spacing: -.02em;
  color: var(--stop);
  font-variant-numeric: tabular-nums;
}
.result-number-caption {
  color: var(--ink); font-weight: 600;
  font-size: var(--t-md); line-height: 1.5;
}
@media (prefers-reduced-motion: no-preference) {
  .result-badge, .result-title, .result-subtitle, .result-number-wrap {
    animation: kadia-fade-up .42s var(--ease) both;
  }
  .result-title { animation-delay: .05s; }
  .result-subtitle { animation-delay: .1s; }
  .result-number-wrap { animation-delay: .15s; }
  .result-number-ring { animation: kadia-ring-pop .5s var(--ease) .3s both; }
}
@keyframes kadia-ring-pop {
  0% { transform: scale(.6); opacity: 0; }
  70% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); }
}

/* what happens next: an ordered list, because it is one */
.result-next {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
  border-top: 1px solid var(--rule);
  padding-top: 20px;
}
.result-next-item {
  display: flex; flex-direction: column; gap: 10px;
  padding: 0 18px;
  border-inline-start: 1px solid var(--rule);
}
.result-next-item:first-child { border-inline-start: 0; padding-inline-start: 0; }
.result-next-item:last-child { padding-inline-end: 0; }
.result-next-item .n {
  width: 28px; height: 28px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink); border-radius: var(--r-plate);
  font-size: var(--t-sm); font-weight: 700; color: var(--ink);
}
.result-next-item p { margin: 0; font-size: var(--t-sm); line-height: 1.62; color: var(--ink-2); }

@media (max-width: 620px) {
  .result-next { grid-template-columns: 1fr; gap: 0; }
  .result-next-item {
    flex-direction: row; align-items: flex-start; gap: 12px;
    padding: 14px 0; border-inline-start: 0;
    border-top: 1px solid var(--rule);
  }
  .result-next-item:first-child { border-top: 0; padding-top: 0; }
  .result-number-wrap { gap: 14px; padding: 14px 16px; }
  .result-number-ring { width: 68px; height: 68px; }
  .result-number { font-size: 1.9rem; }
  .analyzing-title { font-size: var(--t-xl); }
}

/* dashboard: "اعتراضاتي" ticket list - a card-row per ticket instead of a
   flat table, same visual grammar as the office's own admin panel (colored
   status pills, soft shadow on hover) so a customer's own list reads with
   the same polish the office sees internally. */
.dt-list { display: flex; flex-direction: column; gap: 14px; }
/* a real case card, not a table row: a status-coloured rail down the RTL
   start edge, the ticket number as the headline, the facts as a labelled
   grid you can scan vertically, and the actions in their own footer -
   before this everything sat on one line at the same visual weight. */
.dt-row {
  position: relative; overflow: hidden;
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-plate);
  padding: 18px 22px 16px;
  padding-inline-start: 26px;
  transition: border-color .18s ease;
}
.dt-row::before {
  content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; width: 5px;
  background: var(--kadia-border);
}
.dt-row[data-status="matched"]::before,
.dt-row[data-status="letter_generated"]::before,
.dt-row[data-status="document_sent"]::before { background: var(--signal); }
.dt-row[data-status="pending_payment"]::before,
.dt-row[data-status="in_review"]::before { background: var(--caution); }
.dt-row[data-status="submitted"]::before,
.dt-row[data-status="accepted"]::before { background: var(--signal); }
.dt-row[data-status="rejected"]::before { background: var(--stop); }
.dt-row:hover { border-color: var(--signal); }

.dt-row-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.dt-row-id { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.dt-row-kicker { font-size: .72rem; font-weight: 700; color: var(--kadia-text-muted); letter-spacing: .03em; }
.dt-ticket-no { font-weight: 800; color: var(--kadia-navy); font-size: 1.25rem; font-variant-numeric: tabular-nums; line-height: 1.25; }
.dt-row-type { font-size: .84rem; color: var(--kadia-text-muted); font-weight: 700; margin-top: 2px; }

.dt-row-meta {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 12px 18px;
  margin: 16px 0 0; padding-top: 14px;
  border-top: 1px solid var(--kadia-border);
  font-variant-numeric: tabular-nums;
}
.dt-meta-item { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dt-meta-label { color: var(--kadia-text-muted); font-size: .72rem; font-weight: 700; }
.dt-meta-value { color: var(--kadia-navy); font-size: .95rem; font-weight: 700; overflow-wrap: anywhere; }

/* the filing deadline is the one fact that can cost the customer the case,
   so it gets its own pill with real urgency levels instead of coloured text */
.dt-due {
  display: inline-block; padding: 3px 11px; border-radius: var(--r-plate);
  font-size: .82rem; font-weight: 800;
  background: var(--kadia-bg-dim, var(--kadia-bg)); color: var(--kadia-text-muted);
}
.dt-due.soon { background: #fdf3d8; color: #8a6508; }
.dt-due.urgent { background: #fdecea; color: var(--kadia-danger); }

.dt-row-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.dt-row-actions .btn { flex: 0 1 auto; }

@media (max-width: 640px) {
  .dt-row { padding: 16px 16px 14px; padding-inline-start: 20px; }
  .dt-ticket-no { font-size: 1.12rem; }
  .dt-row-actions .btn { flex: 1 1 auto; }
  /* two fixed columns rather than auto-fit: one item per row made a
     four-fact card ~400px tall, so a short ticket list became a long scroll */
  .dt-row-meta { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}

/* empty until its ticket's "Details" button is clicked - collapsing it
   when empty keeps the list's flex gap from doubling up between every row */
.dt-row-detail:empty { display: none; }

.dt-detail-card {
  background: var(--plate); border: 1px solid var(--rule); border-radius: var(--r-plate);
  padding: 24px 22px; margin-top: 14px;
}
.dt-detail-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.dt-detail-header h3 { margin: 0; color: var(--kadia-navy); font-size: 1.2rem; }
.dt-detail-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.dt-detail-meta { color: var(--kadia-text-muted); font-size: .9rem; line-height: 2; margin-bottom: 6px; }
.dt-detail-meta strong { color: var(--kadia-text); }

/* legacy alias kept for the ticket-detail box markup used elsewhere */
.ticket-detail-box { background: #fbfbf7; border: 1px solid var(--kadia-border); border-radius: var(--r-ctl); padding: 16px; margin-top: 12px; }
.ticket-detail-box h3 { margin: 0 0 10px; color: var(--kadia-navy); }
.ticket-detail-box p { margin: 6px 0; line-height: 1.8; }

/* ---------- auth (auth.html / reset-password.html) ---------- */
/* a two-field sign-in form does not need an 800px card - the narrower shell
   plus a real page heading make this read as a focused entry point rather
   than a wizard step that lost its content */
.auth-shell { max-width: 460px; }
.auth-intro { text-align: center; margin-bottom: 24px; }
.auth-intro h1 { font-size: 1.7rem; font-weight: 800; color: var(--kadia-navy); margin: 0 0 8px; letter-spacing: -.015em; }
.auth-intro p { color: var(--kadia-text-muted); margin: 0 auto; max-width: 38ch; line-height: 1.7; font-size: .95rem; }
.auth-card { border: 1px solid var(--rule); border-radius: var(--r-ctl); padding: 26px 24px 24px; }

/* Google's rendered button carries its own required chrome (font, exact
   blue, corner radius) - not something this system can restyle, and not
   trying to is deliberate: it needs to keep reading as Google's own control
   for a user to trust it. The slot just centers it and gives it the same
   full-bleed width as every other primary action on this card. */
.google-signin-slot {
  display: flex; justify-content: center;
  min-height: 44px; margin-bottom: 20px;
}
.google-signin-slot > div { width: 100% !important; }
.google-signin-slot iframe { margin: 0 auto; }

/* Placeholder shown while Google's script/config is still loading - same
   footprint as the real button so nothing jumps when it's swapped in. A
   plain flat plate, not a shimmer: motion here would read as "still
   broken," not "loading." */
.social-btn-skeleton {
  width: 100%; height: 44px;
  border: 1px solid var(--rule); border-radius: var(--r-ctl);
  background: var(--paper);
}

/* Facebook's own guidelines are looser than Google's about restyling the
   button, so this one is a normal KADIA outline button rather than an
   SDK-rendered widget - it can be visible and clickable immediately, unlike
   Google's slot above which has to wait for Google's own script. */
.btn-social {
  width: 100%; margin-bottom: 12px;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule);
  box-shadow: none;
}
.btn-social:hover { border-color: var(--signal); background: var(--paper); }
.btn-social-facebook { color: #1877F2; }
.btn-social-facebook svg { color: #1877F2; }

/* "or" - a line broken by a label, not a bare word floating in space */
.auth-divider {
  display: flex; align-items: center; gap: 14px;
  margin: 0 0 20px;
  color: var(--ink-3); font-size: var(--t-sm); font-weight: 500;
}
.auth-divider::before, .auth-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--rule);
}

/* segmented control: one track, one moving pill - two solid buttons of equal
   weight never made it obvious which side was actually active */
.auth-tabs {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-ctl); padding: 4px;
  margin-bottom: 24px;
}
.auth-tab {
  border: none; background: none; cursor: pointer;
  font-family: inherit; font-weight: 500; font-size: var(--t-md);
  color: var(--ink-3);
  padding: 11px 12px; border-radius: 9px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.auth-tab:hover { color: var(--kadia-navy); }
.auth-tab.active {
  background: var(--ink); color: var(--paper); font-weight: 600;
  box-shadow: none;
}
.auth-tab:focus-visible { outline: 2px solid var(--kadia-teal); outline-offset: 2px; }
.auth-card .btn-primary {
  background: var(--signal);
  box-shadow: none;
  padding-block: 15px;
}

/* ---------- legal / content pages ---------- */
/* a titled header block using the same kicker-pill language as the homepage
   sections, so terms/privacy/accessibility open like documents instead of
   starting cold on an h1. Each page keeps its own body typography. */
.legal-head { margin-bottom: 34px; padding-bottom: 22px; border-bottom: 1px solid var(--kadia-border); }
.legal-head h1 { font-size: 2rem; font-weight: 800; color: var(--kadia-navy); margin: 0 0 10px; letter-spacing: -.015em; }
.legal-head .updated { color: var(--kadia-text-muted); font-size: .88rem; margin: 0 !important; }

/* ---------- Personal area (dashboard.html) ---------- */
.account-layout { max-width: 1080px; margin: 36px auto 80px; padding: 0 20px; display: flex; align-items: flex-start; gap: 24px; }

.account-sidebar {
  flex: none; width: 250px;
  background: var(--plate); border: 1px solid var(--rule); border-radius: var(--r-plate);
  padding: 22px 14px 14px; position: sticky; top: 20px;
  display: flex; flex-direction: column; gap: 4px;
}
.account-sidebar-profile { text-align: center; padding: 0 8px 18px; border-bottom: 1px solid var(--rule); margin-bottom: 12px; }
.account-avatar {
  width: 58px; height: 58px; border-radius: 50%;
  background: var(--signal);
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; font-weight: 800; margin: 0 auto 12px;
}
.account-sidebar-name { color: var(--ink); font-weight: 800; font-size: .96rem; word-break: break-word; }
.account-sidebar-meta { color: var(--ink-3); font-size: .76rem; margin-top: 6px; line-height: 1.6; }

.account-nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; border-radius: 12px;
  color: var(--ink-2); font-weight: 700; font-size: .92rem;
  background: none; border: none; cursor: pointer; text-align: right;
  font-family: inherit; width: 100%;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
.account-nav-item:hover { background: var(--paper-dim); color: var(--ink); }
.account-nav-item.active { background: var(--signal); color: #fff; }
.account-nav-item.danger { color: var(--stop); }
.account-nav-item.danger:hover { background: var(--stop-tint); color: var(--stop); }
.account-nav-item.danger.active { background: var(--stop); color: #fff; }
.account-nav-item .icon { font-size: 1.05rem; flex: none; line-height: 1; }

.account-main { flex: 1; min-width: 0; }
.account-panel { display: none; }
.account-panel.active { display: block; animation: kadia-fade-up .3s ease-out both; }

/* every panel opened with a bare <h2> hard against the card's top padding;
   a titled header block with a hairline gives each panel a real start */
.account-panel > .wizard-card { border: 1px solid var(--rule); border-radius: var(--r-plate); }
.panel-head { margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid var(--kadia-border); }
.panel-head h2 { margin: 0; color: var(--kadia-navy); font-size: 1.4rem; letter-spacing: -.01em; }
.panel-head p { margin: 8px 0 0; color: var(--kadia-text-muted); font-size: .92rem; line-height: 1.7; }
.account-panel .wizard-card .btn-primary {
  background: var(--signal);
}

/* empty state: a real invitation with an illustrated mark, not a lone emoji
   floating over white */
.dash-empty { text-align: center; padding: 40px 16px 34px; }
.dash-empty-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 78px; height: 78px; border-radius: 24px; margin-bottom: 18px;
  background: var(--kadia-teal-tint); color: var(--kadia-teal-deep, var(--kadia-teal-dark));
  box-shadow: 0 10px 26px rgba(15, 122, 69, .12);
}
.dash-empty-mark svg { display: block; }
.dash-empty h3 { margin: 0 0 8px; color: var(--kadia-navy); font-size: 1.2rem; }
.dash-empty p { color: var(--kadia-text-muted); margin: 0 auto 22px; max-width: 42ch; line-height: 1.75; }

.danger-zone { border-color: #f1c3bb !important; background: var(--stop-tint); }
.danger-zone .panel-head h2 { color: var(--kadia-danger); }
.danger-zone .panel-head { border-bottom-color: #f4d5cf; }
.danger-zone h2 { color: var(--kadia-danger); }
.checkbox-field { display: flex; align-items: flex-start; gap: 8px; margin: 16px 0; }
.checkbox-field input { width: auto; margin-top: 3px; }
.checkbox-field label { font-size: .88rem; color: var(--kadia-text); cursor: pointer; }

@media (max-width: 860px) {
  .account-layout { flex-direction: column; gap: 16px; }
  .account-sidebar { width: 100%; position: static; flex-direction: row; flex-wrap: wrap; padding: 16px 12px; }
  /* the nav's buttons live inside a <nav> wrapper, so making the SIDEBAR a
     wrapping row never reached them - the five full-width nav rows plus the
     stacked profile block filled the whole first phone screen before a single
     ticket was visible. Lay the wrapper out as the wrapping row instead. */
  .account-sidebar > nav { display: flex; flex-wrap: wrap; gap: 8px; width: 100%; }
  .account-nav-item {
    width: auto; flex: 1 1 auto; justify-content: center;
    padding: 10px 14px; font-size: .86rem; text-align: center;
  }
  .account-sidebar-profile {
    flex: 1 0 100%;
    display: flex; align-items: center; gap: 12px; text-align: start;
    padding: 0 4px 14px; margin-bottom: 10px;
  }
  .account-avatar { width: 46px; height: 46px; font-size: 1.1rem; margin: 0; flex: none; }
  .account-sidebar-meta { margin-top: 2px; }
}
/* the teal variant used --kadia-teal on a pale tint (~2.4:1) and the gray one
   #666 on #eee; both are now token-based and clear AA */
.status-pill {
  display: inline-block; flex: none;
  padding: 5px 14px; border-radius: var(--r-plate);
  font-size: 0.8rem; font-weight: 800; letter-spacing: .01em;
  white-space: nowrap;
}
.status-draft, .status-awaiting_payment { background: var(--kadia-bg-dim, #eee); color: #5d5468; }
.status-matched, .status-letter_generated, .status-document_sent { background: var(--kadia-teal-tint); color: var(--kadia-teal-deep, var(--kadia-teal-dark)); }
.status-pending_payment, .status-in_review { background: #fdf3d8; color: #8a6508; }
.status-submitted, .status-accepted { background: var(--kadia-success-tint, #eaf7f0); color: var(--kadia-success); }
.status-rejected { background: #fdecea; color: var(--kadia-danger); }

@media (max-width: 860px) {
  .hero .container { grid-template-columns: 1fr; }
  .grid-3, .grid-2, .method-choice { grid-template-columns: 1fr; }
  .hero { padding: 40px 0 48px; }
  .hero h1 { font-size: 2.05rem; }
  .hero p.lead { max-width: none; }
  .scan-mockup { max-width: 280px; margin-top: 34px; }
}


/* ---------- direction arrows on flow controls ---------- */
/* The bare "←" glyph was stripped out of the translation strings: a lone arrow
   inside an RTL run renders inconsistently across fonts and reverses meaning
   depending on the surrounding bidi context. These are drawn instead, and the
   mask points along the reading direction. */
#toStep2::after, #toStep3::after, #toStep4::after, #toStep5::after,
#payButton::after, #step1ScanContinueBtn::after, #otherReportSubmit::after,
.btn-next::after {
  content: "";
  width: 1em; height: 1em; flex: none;
  background-color: currentColor;
  -webkit-mask: var(--i-arrow) center / contain no-repeat;
          mask: var(--i-arrow) center / contain no-repeat;
}
#backTo1::before, #backTo2::before, #backTo3::before, #backTo4::before,
.step1-back-link::before, .btn-back::before {
  content: "";
  width: 1em; height: 1em; flex: none;
  display: inline-block; vertical-align: -.14em;
  background-color: currentColor;
  -webkit-mask: var(--i-arrow) center / contain no-repeat;
          mask: var(--i-arrow) center / contain no-repeat;
  transform: scaleX(-1);
}


/* ---------- data-icon: an icon that survives translation ---------- */
/* An .ico span placed inside a [data-i18n] element is destroyed the moment
   i18n.js sets textContent on that element. Declaring the icon on the element
   itself draws it from CSS instead, so switching language never removes it. */
[data-icon]::before {
  content: "";
  display: inline-block;
  width: 1em; height: 1em;
  flex: none;
  margin-inline-end: .5em;
  vertical-align: -.14em;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
}
[data-icon="check-ring"]::before { -webkit-mask-image: var(--i-check-ring); mask-image: var(--i-check-ring); }
[data-icon="check"]::before      { -webkit-mask-image: var(--i-check);      mask-image: var(--i-check); }
[data-icon="alert"]::before      { -webkit-mask-image: var(--i-alert);      mask-image: var(--i-alert); }
[data-icon="clock"]::before      { -webkit-mask-image: var(--i-clock);      mask-image: var(--i-clock); }
[data-icon="scale"]::before      { -webkit-mask-image: var(--i-scale);      mask-image: var(--i-scale); }
[data-icon="doc"]::before        { -webkit-mask-image: var(--i-doc);        mask-image: var(--i-doc); }
[data-icon="lock"]::before       { -webkit-mask-image: var(--i-lock);       mask-image: var(--i-lock); }
[data-icon="camera"]::before     { -webkit-mask-image: var(--i-camera);     mask-image: var(--i-camera); }
[data-icon="user"]::before       { -webkit-mask-image: var(--i-user);       mask-image: var(--i-user); }
[data-icon="gift"]::before       { -webkit-mask-image: var(--i-gift);       mask-image: var(--i-gift); }
[data-icon="shield"]::before     { -webkit-mask-image: var(--i-shield);     mask-image: var(--i-shield); }
[data-icon="pin"]::before        { -webkit-mask-image: var(--i-pin);        mask-image: var(--i-pin); }
[data-icon="refresh"]::before    { -webkit-mask-image: var(--i-refresh);    mask-image: var(--i-refresh); }
[data-icon="clip"]::before       { -webkit-mask-image: var(--i-clip);       mask-image: var(--i-clip); }
[data-icon="printer"]::before    { -webkit-mask-image: var(--i-printer);    mask-image: var(--i-printer); }
[data-icon="chat"]::before       { -webkit-mask-image: var(--i-chat);       mask-image: var(--i-chat); }
[data-icon="edit"]::before       { -webkit-mask-image: var(--i-edit);       mask-image: var(--i-edit); }
[data-icon="id"]::before         { -webkit-mask-image: var(--i-id);         mask-image: var(--i-id); }
[data-icon="mail"]::before       { -webkit-mask-image: var(--i-mail);       mask-image: var(--i-mail); }
[data-icon="scan"]::before       { -webkit-mask-image: var(--i-scan);       mask-image: var(--i-scan); }


/* ---------- violation-type icons ---------- */
/* These arrive from the database, where an admin stores an emoji per type.
   Rather than change that data, the eight seeded types get a drawn icon keyed
   off data-value. The shared properties are applied only to those eight, so a
   type an admin adds later simply keeps showing its stored emoji and nothing
   has to change in code. */
/* Genuinely colorful, not a single brand hue: each category gets its own
   solid, high-saturation fill with a white icon on top (ui-ux-pro-max's
   flat-design guidance - solid bright colors, no gradients/shadows). A
   first attempt reused signal-green for all eight, which read as "styled"
   rather than "colorful" - explicit user feedback. Eight distinct hues
   rather than a tighter 4-6-color set because the actual job here is fast
   category recognition in a picker; two categories sharing a color would
   undermine that. Colors lean on real-world association where one exists
   (parking-sign blue, the red/white curb's own red, transit orange) rather
   than being assigned arbitrarily. The stored emoji text stays in the DOM
   (font-size:0 hides it) and the actual glyph is drawn on ::before instead
   of the span itself, so the span is free to be the colored tile. Scoped to
   the same explicit eight values as the fallback comment above promises -
   a bare [data-value] would also catch a future admin-added type, hiding
   its emoji (font-size:0) with no drawn replacement to show instead. */
.chip[data-value="parking"] .chip-ico,
.option-pill[data-value="parking"] .pill-ico,
.chip[data-value="red_white"] .chip-ico,
.option-pill[data-value="red_white"] .pill-ico,
.chip[data-value="lpr_camera"] .chip-ico,
.option-pill[data-value="lpr_camera"] .pill-ico,
.chip[data-value="public_transit_lane"] .chip-ico,
.option-pill[data-value="public_transit_lane"] .pill-ico,
.chip[data-value="officer"] .chip-ico,
.option-pill[data-value="officer"] .pill-ico,
.chip[data-value="scooter"] .chip-ico,
.option-pill[data-value="scooter"] .pill-ico,
.chip[data-value="airport"] .chip-ico,
.option-pill[data-value="airport"] .pill-ico,
.chip[data-value="other"] .chip-ico,
.option-pill[data-value="other"] .pill-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  flex: none;
  border-radius: 10px;
  color: #fff;
  /* rem, not em: font-size:0 hides the stored emoji text node - em width/
     height on ::before would resolve against THIS zeroed font-size (a real
     bug found live: mask-image was present and correct, but every icon
     rendered invisible at 0x0 while the "hidden" emoji stayed visible,
     since font-size:0 doesn't fully suppress color-emoji glyphs in every
     renderer) - rem is relative to the root font-size instead. */
  font-size: 0;
  vertical-align: -.3em;
}
.chip[data-value="parking"] .chip-ico, .option-pill[data-value="parking"] .pill-ico { background: var(--cat-parking); }
.chip[data-value="red_white"] .chip-ico, .option-pill[data-value="red_white"] .pill-ico { background: var(--cat-red_white); }
.chip[data-value="lpr_camera"] .chip-ico, .option-pill[data-value="lpr_camera"] .pill-ico { background: var(--cat-lpr_camera); }
.chip[data-value="public_transit_lane"] .chip-ico, .option-pill[data-value="public_transit_lane"] .pill-ico { background: var(--cat-public_transit_lane); }
.chip[data-value="officer"] .chip-ico, .option-pill[data-value="officer"] .pill-ico { background: var(--cat-officer); }
.chip[data-value="scooter"] .chip-ico, .option-pill[data-value="scooter"] .pill-ico { background: var(--cat-scooter); }
.chip[data-value="airport"] .chip-ico, .option-pill[data-value="airport"] .pill-ico { background: var(--cat-airport); }
.chip[data-value="other"] .chip-ico, .option-pill[data-value="other"] .pill-ico { background: var(--cat-other); }
.chip[data-value="parking"] .chip-ico::before,
.option-pill[data-value="parking"] .pill-ico::before,
.chip[data-value="red_white"] .chip-ico::before,
.option-pill[data-value="red_white"] .pill-ico::before,
.chip[data-value="lpr_camera"] .chip-ico::before,
.option-pill[data-value="lpr_camera"] .pill-ico::before,
.chip[data-value="public_transit_lane"] .chip-ico::before,
.option-pill[data-value="public_transit_lane"] .pill-ico::before,
.chip[data-value="officer"] .chip-ico::before,
.option-pill[data-value="officer"] .pill-ico::before,
.chip[data-value="scooter"] .chip-ico::before,
.option-pill[data-value="scooter"] .pill-ico::before,
.chip[data-value="airport"] .chip-ico::before,
.option-pill[data-value="airport"] .pill-ico::before,
.chip[data-value="other"] .chip-ico::before,
.option-pill[data-value="other"] .pill-ico::before {
  content: "";
  width: 16px; height: 16px;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
}

.chip[data-value="parking"] .chip-ico::before,
.option-pill[data-value="parking"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-parking); mask-image: var(--i-v-parking);
}
.chip[data-value="red_white"] .chip-ico::before,
.option-pill[data-value="red_white"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-curb); mask-image: var(--i-v-curb);
}
.chip[data-value="lpr_camera"] .chip-ico::before,
.option-pill[data-value="lpr_camera"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-lpr); mask-image: var(--i-v-lpr);
}
.chip[data-value="public_transit_lane"] .chip-ico::before,
.option-pill[data-value="public_transit_lane"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-bus); mask-image: var(--i-v-bus);
}
.chip[data-value="officer"] .chip-ico::before,
.option-pill[data-value="officer"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-officer); mask-image: var(--i-v-officer);
}
.chip[data-value="scooter"] .chip-ico::before,
.option-pill[data-value="scooter"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-scooter); mask-image: var(--i-v-scooter);
}
.chip[data-value="airport"] .chip-ico::before,
.option-pill[data-value="airport"] .pill-ico::before {
  -webkit-mask-image: var(--i-v-plane); mask-image: var(--i-v-plane);
}
.chip[data-value="other"] .chip-ico::before,
.option-pill[data-value="other"] .pill-ico::before {
  -webkit-mask-image: var(--i-doc); mask-image: var(--i-doc);
}

:root {
  --i-v-parking: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.2' y='3.2' width='17.6' height='17.6' rx='3'/%3E%3Cpath d='M9.4 17V7.6h3.4a2.9 2.9 0 0 1 0 5.8H9.4'/%3E%3C/svg%3E");
  --i-v-curb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.6' y='9' width='18.8' height='6' rx='1.4'/%3E%3Cpath d='M7.4 9 4.6 15M13 9l-2.8 6M18.6 9l-2.8 6'/%3E%3C/svg%3E");
  --i-v-bus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='3.4' width='16' height='13.4' rx='2.4'/%3E%3Cpath d='M4 10.6h16M8.4 3.4v7.2M15.6 3.4v7.2'/%3E%3Ccircle cx='8' cy='19.4' r='1.7'/%3E%3Ccircle cx='16' cy='19.4' r='1.7'/%3E%3C/svg%3E");
  --i-v-officer: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.6 4.8 5.4v5.2c0 4.3 3 8.2 7.2 9.2 4.2-1 7.2-4.9 7.2-9.2V5.4Z'/%3E%3Cpath d='m12 7.4 1.4 2.9 3.2.5-2.3 2.2.5 3.2-2.8-1.5-2.8 1.5.5-3.2-2.3-2.2 3.2-.5Z'/%3E%3C/svg%3E");
  --i-v-scooter: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='5.4' cy='17.6' r='2.8'/%3E%3Ccircle cx='18.6' cy='17.6' r='2.8'/%3E%3Cpath d='M15.8 17.6h-6a2.6 2.6 0 0 0-2.6-2.6M15.4 4.2h2.2l1 13.4'/%3E%3C/svg%3E");
  --i-v-plane: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.2 21.4 12 15.6l7.2-2.2a2 2 0 0 0 0-3.8L12 7.4 10.2 1.6a1 1 0 0 0-1.9 0L6.6 7.4l-3.4 1a1.4 1.4 0 0 0 0 2.7l3.4 1 1.7 5.8a1 1 0 0 0 1.9 0Z' transform='rotate(45 12 12)'/%3E%3C/svg%3E");
  /* a bare camera (--i-camera, reused for every other "photo" affordance on
     the site) didn't say "reads your plate" - this pairs the camera with
     the plate it's aimed at, which is the actual distinguishing feature of
     an LPR ticket versus any other camera-issued one. */
  --i-v-lpr: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='12' height='8.2' rx='2.2'/%3E%3Ccircle cx='9' cy='7.1' r='2.1'/%3E%3Cpath d='M15 5 19.4 3v8.2L15 9.2'/%3E%3Crect x='5.4' y='16.6' width='13.2' height='4.4' rx='1.2'/%3E%3Cpath d='M10.4 16.6v4.4M14.8 16.6v4.4'/%3E%3C/svg%3E");
}

/* ============================================================================
   Mobile app shell
   ----------------------------------------------------------------------------
   Below 768px the task surfaces (the wizard, the vault) stop behaving like a
   scrolling document and behave like an app: a compact bar pinned to the top,
   the content scrolling between them, and the primary action fixed in the
   thumb zone above the home indicator. Everything here is scoped to the
   breakpoint — the desktop layout is untouched.
   ============================================================================ */

/* --- touch feel, everywhere --- */
/* iOS paints a grey box over anything tappable unless told not to; the real
   feedback is the :active state below, which is instant and on-brand. */
a, button, [role="button"], .btn, .option-pill, .method-card,
.chip, .faq-q, .account-nav-item, .lang-seg-btn, .nav-hamburger {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;          /* removes the legacy 300ms tap delay */
}
.btn:active, .option-pill:active, .method-card:active,
.account-nav-item:active, .lang-seg-btn:active {
  transform: scale(.985);
  /* Response on press must be near-instant; release gets a touch more give -
     matches how a real button feels versus how it recovers. */
  transition: transform .08s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .btn:active, .option-pill:active, .method-card:active,
  .account-nav-item:active, .lang-seg-btn:active { transform: none; }
}
/* Chrome on the interface should not be selectable — dragging a label and
   getting a text selection is the clearest "this is a web page" tell. */
.site-header, .app-bar, .progress-track, .progress-header,
.step1-subnav, .report-head, .report-verdict-bar, .btn, .nav-hamburger,
.lang-toggle-btn, .lang-seg-btn, .account-nav-item {
  -webkit-user-select: none; user-select: none;
}
/* but never on anything the user may need to copy */
.letter-preview, .report-label, input, textarea, p, td {
  -webkit-user-select: text; user-select: text;
}

@media (max-width: 767px) {
  /* the whole-page rubber band belongs to documents, not apps */
  html, body { overscroll-behavior-y: none; }

  /* ---- the app bar ---- */
  /* 56px, the platform's own height, replacing a 81px marketing header -
     compact like a native app's title bar, but paper, not ink: an inverted
     dark bar here read as a leftover from an earlier design, disconnected
     from the light header used everywhere else on the site. */
  body.wizard-page .site-header,
  body.account-page .site-header {
    padding-top: env(safe-area-inset-top, 0px);
  }
  body.wizard-page .site-header .bar,
  body.account-page .site-header .bar {
    min-height: 56px;
    padding-top: 0; padding-bottom: 0;
    gap: 10px;
  }
  body.wizard-page .brand-text,
  body.account-page .brand-text { font-size: 1.05rem; }
  body.wizard-page .brand-icon,
  body.account-page .brand-icon { width: 27px; height: 27px; }

  body.wizard-page .lang-seg-btn,
  body.account-page .lang-seg-btn { min-height: 34px; padding: 5px 11px; }

  body.wizard-page .nav-actions .btn,
  body.account-page .nav-actions .btn { min-height: 44px; padding: 6px 13px; font-size: var(--t-sm); }

  /* An app bar is one row. The generic header rule drops .nav-actions onto its
     own full-width line below 480px, which is right for the marketing header
     but turned the wizard/vault bar into a 90px two-decker. */
  body.wizard-page .site-header .bar,
  body.account-page .site-header .bar {
    flex-wrap: nowrap !important;
    row-gap: 0 !important;
  }
  body.wizard-page .site-header .bar .nav-actions,
  body.account-page .site-header .bar .nav-actions {
    width: auto !important;
    justify-content: flex-end !important;
    flex-wrap: nowrap;
  }

  /* the vault's own section switcher is a primary navigation control */
  .account-nav-item { min-height: 44px; }
}

/* the vault's section switcher, at every width */
@media (max-width: 767px) {
  .account-nav-item { min-height: 44px; }

  /* ---- the screen ---- */
  /* Content scrolls between a pinned bar and a pinned action, so the page
     itself is exactly the viewport and never taller. dvh tracks Safari's
     collapsing toolbars; vh is the fallback for older engines. */
  body.wizard-page .wizard-shell,
  body.account-page .account-layout {
    padding-inline: 0;
  }
  body.wizard-page .wizard-card {
    border-radius: 0;
    border-inline: 0;
    box-shadow: none;
    padding: 20px 18px 24px;
    /* room for the fixed action bar plus the home indicator */
    padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  }

  /* ---- the action bar ---- */
  /* One surface, not a floating pill: it sits on its own ground with a hairline
     above it, so content scrolling underneath never appears to touch it. */
  .sticky-cta-bar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 60;
    width: auto;
    /* individual CTAs cap their own width for the desktop layout
       (.step1-scan-continue is 320px); in the action bar they span it */
    max-width: none;
    margin: 0;
    border-radius: 0;
    min-height: 56px;
    font-size: var(--t-lg);
    box-shadow: 0 -1px 0 var(--rule), 0 -12px 28px -18px rgba(19,23,26,.5);
    padding-bottom: calc(13px + env(safe-area-inset-bottom, 0px));
    padding-top: 13px;
  }
  /* Only the wizard and the vault have an action bar pinned to the bottom, so
     only there do the floating buttons need lifting. Raising them everywhere
     parked them in the middle of the marketing pages' content — on the home
     page the accessibility button sat directly on top of one of the inspection
     report's verdicts. */
  body.wizard-page .a11y-widget-btn,
  body.account-page .a11y-widget-btn { bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
  body.wizard-page .contact-widget-btn,
  body.account-page .contact-widget-btn { bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
  body:not(.wizard-page):not(.account-page) .a11y-widget-btn,
  body:not(.wizard-page):not(.account-page) .contact-widget-btn {
    bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  }
  /* Pages that carry the bottom tab bar (see .bottom-tab-bar below) need the
     same lift the wizard/account pages get, for the same reason - :has()
     rather than a body class so no page needs new markup beyond the nav
     itself, and it can't drift out of sync with which pages actually have
     the bar. Repeats the :not() pair from the rule above (always true here,
     since this page is neither) purely to match its specificity - a bare
     :has() version silently lost to that earlier, more specific rule and
     never actually lifted the buttons, caught live (the a11y button
     overlapped the tab bar's own account label). */
  body:has(.bottom-tab-bar):not(.wizard-page):not(.account-page) .a11y-widget-btn,
  body:has(.bottom-tab-bar):not(.wizard-page):not(.account-page) .contact-widget-btn {
    bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  }

  /* ---- bottom tab bar ---- */
  /* A UX pattern noted from a competitor's mobile app (lofrayer.app) -
     applied here as a navigation idea only, with this site's own icon set,
     copy and destinations, not their content: a fixed three-item bar with
     the primary action raised as a circular button reads as an installed
     app's own navigation, reinforcing the standing "mobile is a web app,
     not a website" requirement this whole redesign is built around. Present
     only on index.html for now (the wizard and account pages already have
     their own pinned action bar in this exact spot - a second fixed bottom
     bar there would compete with it, not complement it). */
  body:has(.bottom-tab-bar) { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
  .bottom-tab-bar {
    position: fixed; inset-inline: 0; bottom: 0; z-index: 70;
    display: flex; align-items: flex-end; justify-content: space-around;
    background: var(--plate);
    border-top: 1px solid var(--rule);
    padding: 6px 12px calc(6px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -1px 0 var(--rule), 0 -12px 28px -18px rgba(19,23,26,.5);
  }
  .bottom-tab {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    min-width: 64px; min-height: 48px;
    padding: 4px 6px;
    color: var(--ink-3);
    font-size: .68rem; font-weight: 600;
  }
  .bottom-tab .ico { font-size: 1.3rem; }
  .bottom-tab.is-active { color: var(--signal); }
  .bottom-tab-fab {
    display: flex; align-items: center; justify-content: center;
    width: 52px; height: 52px; flex: none;
    margin-top: -22px;
    border-radius: 50%;
    border: 3px solid var(--paper);
    background: var(--signal); color: #fff;
    box-shadow: 0 6px 16px rgba(15, 122, 69, .4);
  }
  .bottom-tab-fab .ico { font-size: 1.35rem; }
  .bottom-tab-fab:hover { background: var(--kadia-teal-dark); }

  /* ---- scrolling regions behave like app scroll views ---- */
  .chat-log, .account-main, .letter-preview {
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  /* ---- inputs ---- */
  /* Safari zooms the whole page when a focused field is under 16px. This is a
     browser behaviour being prevented, not a style preference, so it has to
     beat any component's own font-size — .chat-textarea sets .95rem and its
     class specificity would otherwise win. */
  input:not([type="checkbox"]):not([type="radio"]),
  select, textarea { font-size: 16px !important; }

  /* a text link is still a tap target */
  .chat-elaboration-skip {
    min-height: 44px;
    display: inline-flex; align-items: center;
    padding-inline: 2px;
  }
}

/* Standalone (added to the home screen): there is no browser chrome to fall
   back on, so the header must own the status-bar area itself - on every
   page, not just the wizard/account app-bar. A real bug found live: this
   rule only ever targeted body.wizard-page/body.account-page, so opening
   the marketing header (home, legal pages, auth) as an installed iPhone
   app left it sitting with no top padding, directly under the translucent
   status bar - the language toggle and logo rendered half-covered by the
   clock/battery icons. */
@media (display-mode: standalone) {
  .site-header { padding-top: env(safe-area-inset-top, 0px); }
  body { padding-bottom: env(safe-area-inset-bottom, 0px); }
  /* a standalone app has no back button of its own */
  .site-header .nav-links { display: none; }
}


/* ---------- tap targets that text links quietly fail ---------- */
/* A link styled as inline text is still something a thumb has to hit. These
   four sat between 16px and 36px; the floor is 44. */
.brand { min-height: 44px; }
.link-btn, .step1-manual-link, .step1-back-link, .chat-attach-label {
  display: inline-flex; align-items: center;
  min-height: 44px;
}
.chat-attach-label { gap: 7px; }
.chat-attach-label::before {
  content: "";
  width: 1em; height: 1em; flex: none;
  background-color: currentColor;
  -webkit-mask: var(--i-clip) center / contain no-repeat;
          mask: var(--i-clip) center / contain no-repeat;
}


/* the vault's section switcher and its inline buttons are navigation, so they
   take the same 44px floor as everything else a thumb has to hit */
.account-nav-item { min-height: 44px; }
.account-panel .btn-outline, .dt-row .btn { min-height: 44px; }


/* the sign-in / register switcher is the first control on the page and was 40px */
.auth-tab { min-height: 44px; }


/* Footer links are navigation, not prose, so WCAG 2.5.5's inline-link
   exemption does not cover them; they were 24px on every page. The gap on
   .footer-links shrinks to compensate so the column does not grow taller. */
@media (max-width: 767px) {
  .footer-links { gap: 0; }
  .footer-links a { display: flex; align-items: center; min-height: 44px; }
}


/* the FAQ expander's direction cue, drawn rather than a typed arrow glyph */
#faqToggle::after {
  content: "";
  width: 1em; height: 1em; flex: none;
  margin-inline-start: 2px;
  background-color: currentColor;
  -webkit-mask: var(--i-arrow) center / contain no-repeat;
          mask: var(--i-arrow) center / contain no-repeat;
  transform: rotate(-90deg);
}
#faqToggle.is-expanded::after { transform: rotate(90deg); }

/* Shadows in this world are ink with offset and blur. A saturated colour glow
   under a button is decoration — it says nothing about elevation. */
.btn-primary, .btn-block, .footer-cta,
.contact-widget-btn, .promo-strip-cta, #payButton, #toStep3, #toStep4 {
  box-shadow: none;
}
.contact-widget-btn { box-shadow: 0 2px 4px rgba(19,23,26,.14), 0 10px 24px -10px rgba(19,23,26,.4); }
.contact-widget-btn:hover { box-shadow: 0 2px 4px rgba(19,23,26,.18), 0 12px 26px -10px rgba(19,23,26,.5); }
#payButton:hover, #toStep3:hover, #toStep4:hover { box-shadow: none; }


/* ---------- the signed-in header link ---------- */
/* "Hello, <name> · my vault" is a nowrap string that was 173px wide inside a
   59px header slot on a phone, overflowing straight across the logo. The
   greeting is a desktop nicety; the destination is the part that has to be
   there. */
.nav-vault-link { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.nav-greeting { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-vault-label::before {
  content: "";
  display: inline-block;
  width: 1em; height: 1em;
  vertical-align: -.14em;
  margin-inline-end: 5px;
  background-color: currentColor;
  -webkit-mask: var(--i-lock) center / contain no-repeat;
          mask: var(--i-lock) center / contain no-repeat;
}
@media (max-width: 700px) {
  .nav-greeting { display: none; }
}


/* the contact block's mail and phone links are targets, not prose */
.contact-box-lines a { display: inline-flex; align-items: center; min-height: 44px; }

/* ============================================================================
   Violation-type cards — "ticket stub" template (2026-08-28)
   ----------------------------------------------------------------------------
   Replaces the colored-square/emoji grid with a genuinely different shell:
   a white card with an ink-strength edge and a dotted "perforation" line
   near the top - the same paper-stub language as .ticket-perf in the hero
   mockup, so picking a category reads as "which kind of ticket is this"
   rather than a generic app icon-picker any product could ship. A big
   circular badge in one accent color per category (richer/deeper than the
   old flat-saturated set, so the CARD stays quiet and only the badge
   carries color) replaces the small colored square. `.chip`/`.chip-ico`
   classes are kept alongside these on the same elements on purpose - the
   existing per-category ::before glyph-drawing rules key off
   `.chip[data-value] .chip-ico`, so this only adds the new shell/size/color
   around that, it doesn't fork the icon-drawing system. Used by both the
   inline "we cover every type" section and the mobile category sheet
   (violationCardsHtml() in index.html emits one markup for both). */
.chip-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
  max-width: 720px; margin: 0 auto;
}
/* a.chip.vtype-card (element + two classes) rather than plain .vtype-card:
   the pre-existing .chip[data-value="X"] mobile rule (a class + an
   attribute selector) ties this on specificity, and being defined earlier
   is not enough to win a tie - it has to out-specify it outright, on every
   viewport, not just win on desktop where that older rule doesn't apply. */
a.chip.vtype-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 14px;
  background: var(--plate);
  border: 1.5px solid var(--rule-strong);
  border-radius: var(--r-plate);
  padding: 30px 12px 22px;
  position: relative;
  color: var(--ink);
  font-weight: 700;
  box-shadow: none;
  aspect-ratio: auto;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
a.chip.vtype-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
@media (hover: none) { a.chip.vtype-card:hover { transform: none; box-shadow: none; } }
.vtype-perf {
  position: absolute; top: 10px; inset-inline: 16px; height: 0;
  border-top: 2px dotted var(--rule);
}
/* Each card names its own accent once, as a custom property, instead of
   repeating the hex per property - the badge fill and its resting shadow
   both read off --v-color, so they can never drift out of sync. */
.vtype-card[data-value="parking"]             { --v-color: #3b6fc4; }
.vtype-card[data-value="red_white"]           { --v-color: #c2453f; }
.vtype-card[data-value="lpr_camera"]          { --v-color: #7256d1; }
.vtype-card[data-value="public_transit_lane"] { --v-color: #cf7a1f; }
.vtype-card[data-value="officer"]             { --v-color: #4a3f96; }
.vtype-card[data-value="scooter"]             { --v-color: #10897c; }
.vtype-card[data-value="airport"]             { --v-color: #1088a3; }
.vtype-card[data-value="other"]               { --v-color: #6b7280; }

/* Bigger, and given real presence: a resting colored shadow (this picker's
   own deliberate exception to the site's "no saturated glows" rule - named
   here the same way the scan beam and the promo strip's live dot are, in
   DESIGN.md - because for a "which kind of ticket is this" moment, a badge
   that just sits flat on the page undersells the choice). A slow, gentle
   float keeps every badge quietly alive without asking for attention -
   amplitude is small and the timing is staggered per card (off --tile-i)
   so eight badges never bob in unison, which would read as a glitch, not
   as alive. Hover/tap gets the real payoff: a springy scale + tilt. */
/* a.chip.vtype-card .chip-ico.vtype-badge, not bare .vtype-badge: the
   pre-existing .chip[data-value="X"] .chip-ico rule (a class + attribute +
   class) still applies at every width, not just mobile, and outspecifies
   a single class - caught live, the badge was rendering at the old 30px
   regardless of this rule's width:72px. */
a.chip.vtype-card .chip-ico.vtype-badge {
  width: 72px; height: 72px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  color: #fff;
  background: var(--v-color);
  box-shadow: 0 10px 22px -8px var(--v-color), 0 2px 6px rgba(19, 23, 26, .12);
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1), box-shadow .3s ease;
}
a.chip.vtype-card .chip-ico::before { width: 36px; height: 36px; }
/* zero-size + clipped, not font-size:0 - a color emoji glyph isn't
   reliably suppressed by a zero font-size in every mobile renderer (caught
   live: the category sheet was showing raw 🅿️/🚧/📷 emoji on top of the
   drawn icon underneath). Actual clipping is unconditional. */
.chip-emoji-fallback { position: absolute; width: 0; height: 0; overflow: hidden; }
.vtype-label { font-size: var(--t-md); line-height: 1.3; }

a.chip.vtype-card:hover .vtype-badge {
  transform: scale(1.12) rotate(-6deg);
  box-shadow: 0 16px 28px -8px var(--v-color), 0 4px 10px rgba(19, 23, 26, .16);
}
a.chip.vtype-card:active .vtype-badge { transform: scale(.96) rotate(0deg); transition-duration: .1s; }

@media (prefers-reduced-motion: no-preference) {
  .vtype-card { animation: kadia-tile-pop .38s var(--ease) both; animation-delay: calc(var(--tile-i, 0) * 45ms); }
  .vtype-badge {
    animation: vtype-float 3.6s ease-in-out calc(var(--tile-i, 0) * .3s) infinite;
  }
  /* animation: none, not animation-play-state: paused - a paused CSS
     animation still holds and freezes its last computed transform, which
     keeps outranking the plain :hover transform below it (caught live:
     the hover scale+tilt never visibly applied, frozen mid-float instead).
     Fully removing the animation hands transform back to the normal
     cascade, where the higher-specificity hover rule can actually win. */
  a.chip.vtype-card:hover .vtype-badge, a.chip.vtype-card:active .vtype-badge {
    animation: none;
  }
}
@keyframes vtype-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}

@media (max-width: 767px) {
  .chip-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .vtype-card { padding: 26px 10px 18px; }
}
.category-sheet .chip-grid { max-width: none; }

/* ---- cookie notice bar (consent.js) ---- */
/* notice-and-continue model (Amendment 13 does not require an opt-in gate
   for standard cookies the way EU ePrivacy does) - a slim full-width strip,
   never a modal/overlay that blocks the page, matching how Israeli public
   bodies (e.g. Tel Aviv Municipality) present the same notice. */
.kadia-consent-overlay {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 200;
}
.kadia-consent-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
  background: var(--kadia-navy);
  color: #fff;
  padding: 12px 20px;
  box-shadow: 0 -4px 20px rgba(45, 27, 78, .18);
}
.kadia-consent-bar p { margin: 0; font-size: .85rem; line-height: 1.6; color: #fff; opacity: .92; }
.kadia-consent-bar p a { color: var(--kadia-teal-light); text-decoration: underline; margin: 0 2px; }
.kadia-consent-bar .btn { flex-shrink: 0; padding: 8px 22px; font-size: .85rem; }
/* While the notice is on screen, push the page (and anything fixed to the
   bottom of it, i.e. the wizard's .sticky-cta-bar) clear of it. Set by
   consent.js from the bar's measured height - see the note there. */
body.has-consent-notice { padding-bottom: var(--kadia-consent-inset, 0px); }
body.has-consent-notice .sticky-cta-bar { bottom: var(--kadia-consent-inset, 0px); }
/* The wizard card already reserves 84px for the fixed action bar (see the
   max-width:767px block above); with the notice up, the bar sits that much
   higher, so the card needs the same amount more. */
body.has-consent-notice.wizard-page .wizard-card {
  padding-bottom: calc(84px + var(--kadia-consent-inset, 0px) + env(safe-area-inset-bottom, 0px));
}
.kadia-consent-reopen {
  display: inline;
  color: inherit;
  opacity: .75;
  font-size: inherit;
  text-decoration: none;
  cursor: pointer;
}
.kadia-consent-reopen:hover { opacity: 1; text-decoration: underline; }
.kadia-consent-actions { display: flex; gap: 8px; flex-shrink: 0; }
/* "decline" is an equal choice, not a hidden link - same size as "accept",
   outlined so it reads on the navy bar */
.kadia-consent-bar .kadia-consent-decline {
  background: transparent; color: #fff; border: 1px solid rgba(255, 255, 255, .55);
}
.kadia-consent-bar .kadia-consent-decline:hover { background: rgba(255, 255, 255, .1); }
/* 2026-09-30 (audit P1-5): on a 375px phone the bar used to stack its text
   above a full-width button, covering about a quarter of the screen. Now one
   row - text beside compact buttons - so it stays a strip at the bottom. */
@media (max-width: 640px) {
  .kadia-consent-bar { flex-wrap: nowrap; justify-content: space-between; gap: 10px; padding: 8px 12px; }
  .kadia-consent-bar p { font-size: .78rem; line-height: 1.45; text-align: start; }
  .kadia-consent-bar .btn { min-height: 40px; padding: 6px 12px; font-size: .8rem; }
}

/* ---- lookup-tool cross-promo strip (index.html, between the hero and "how
   it works"). Third pass: dropped the dark card look entirely (both the
   borrowed /lookup neon palette and the --ink "dark card" version that
   followed it - neither read right against the rest of this light site).
   Bright and warm instead, built from --signal-tint/--caution-tint (this
   site's own existing "light, energetic surface" tokens, not new colors)
   blended into one diagonal glow - lively without leaving the palette. */
.lookup-cta-strip {
  padding: 64px 0;
  background: linear-gradient(120deg, var(--signal-tint) 0%, var(--caution-tint) 100%);
}
.lookup-cta-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 44px;
  flex-wrap: wrap;
}
.lookup-cta-copy { flex: 1 1 360px; min-width: 0; }
.lookup-cta-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: .78rem; letter-spacing: .02em; color: var(--signal);
  background: #fff; border: 1px solid rgba(15,122,69,.25);
  padding: 6px 14px; border-radius: 999px; margin-bottom: 18px;
}
.lookup-cta-live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--signal); flex: none; }
.lookup-cta-inner h2 {
  color: var(--ink); font-size: clamp(1.4rem, 2.6vw, 1.85rem); font-weight: 800;
  margin: 0 0 12px; line-height: 1.35; text-wrap: balance;
}
/* the reassurance is the punchline of the headline, not a caption under
   it - same size family as the question, own line, in the brand's
   "finding" green so it visually resolves the question right above it. */
.lookup-cta-reassure { display: block; color: var(--signal); margin-top: 2px; }
.lookup-cta-inner p { color: var(--ink-2); margin: 0 0 20px; font-size: 1rem; line-height: 1.7; max-width: 44ch; }
.lookup-cta-points { list-style: none; margin: 0 0 26px; padding: 0; display: flex; flex-wrap: wrap; gap: 10px 24px; }
.lookup-cta-points li { display: flex; align-items: center; gap: 8px; font-size: .88rem; color: var(--ink-2); font-weight: 600; }
.lookup-cta-points .ico { color: var(--signal); flex: none; }
/* reuses .btn.btn-primary (the site's one real button style) rather than a
   bespoke gradient pill - "fits our site" was as much about inventing a
   second button style as it was about color. */
.lookup-cta-btn .ico-arrow { transition: transform .18s var(--ease); }
.lookup-cta-btn:hover .ico-arrow { transform: translateX(-4px); }

/* signature visual: the real "before" photo (see index.html's own comment
   on the img), just a clean white-framed panel now - no overlay text on
   top of it, the reassurance already lives in the headline. */
.lookup-cta-visual { flex: 1 1 420px; max-width: 560px; min-width: 0; }
.lookup-cta-photo-frame {
  border-radius: 20px;
  overflow: hidden;
  border: 4px solid #fff;
  box-shadow: var(--shadow-lg);
}
.lookup-cta-photo { display: block; width: 100%; height: auto; aspect-ratio: 1408 / 768; object-fit: cover; }

@media (prefers-reduced-motion: no-preference) {
  .lookup-cta-live-dot { animation: lk-cta-pulse-dot 1.6s ease-in-out infinite; }
}
@keyframes lk-cta-pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

@media (max-width: 780px) {
  .lookup-cta-inner { flex-direction: column; }
  /* flex-basis is a main-axis size - on the row layout above that's width
     (420px, intended), but flex-direction:column here makes the main axis
     vertical, so the same 420px would otherwise force the photo container
     to that height regardless of its actual (much shorter) content. */
  .lookup-cta-visual { flex: none; order: -1; max-width: none; }
  .lookup-cta-copy { flex: none; text-align: center; }
  .lookup-cta-eyebrow { margin-inline: auto 0; }
}
@media (max-width: 640px) {
  .lookup-cta-strip { padding: 40px 0; }
  .lookup-cta-inner { align-items: stretch; text-align: center; }
  .lookup-cta-eyebrow { align-self: center; }
  .lookup-cta-inner p { max-width: none; }
  .lookup-cta-points { justify-content: center; }
  .lookup-cta-btn { width: 100%; justify-content: center; }
}

/* ===================== missing-fields dialog (wizard step 1) =====================
   Audit finding 13: validation used to write its message into #alertBox at the
   top of the page and then scroll the user down to the field, so the message
   and the field it referred to were never visible at the same time - and it
   reported one problem at a time. This dialog states every missing field at
   once, in front of the user, with each line jumping to its own field.
   Built from the existing tokens and the .wizard-card surface treatment, not
   a new visual language. */
.kadia-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(19, 23, 26, 0.5);
  animation: kadia-fade-up 0.18s var(--ease) both;
}
.kadia-dialog-overlay[hidden] { display: none !important; }
.kadia-dialog {
  background: var(--plate);
  border: 1px solid var(--rule);
  border-radius: var(--r-card, 16px);
  box-shadow: var(--shadow-lg, 0 24px 60px -20px rgba(19, 23, 26, .45));
  padding: 26px 24px 22px;
  width: 100%;
  max-width: 460px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  animation: kadia-fade-up 0.24s var(--ease) both;
}
.kadia-dialog h3 { margin: 0 0 6px; font-size: 1.15rem; font-weight: 800; }
.kadia-dialog > .hint { margin: 0 0 16px; }
.kadia-dialog-list { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.kadia-dialog-list button {
  /* a real button: keyboard-reachable, and it does something (jumps to the
     field), so it has to look interactive rather than like list text */
  width: 100%;
  /* label above reason, not beside it: side by side, a two-word field name
     like "סוג העבירה" wrapped onto two lines while its explanation sat on
     one, which read as broken rather than dense */
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: start;
  font: inherit;
  color: var(--ink);
  background: var(--stop-tint, #fbeceb);
  border: 1px solid transparent;
  border-inline-start: 3px solid var(--stop, #b3261e);
  border-radius: var(--r-field, 10px);
  padding: 11px 13px;
  cursor: pointer;
  transition: border-color .16s var(--ease), transform .16s var(--ease);
}
.kadia-dialog-list button:hover { border-color: var(--stop, #b3261e); transform: translateX(-2px); }
.kadia-dialog-list button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.kadia-dialog-list .vd-label { font-weight: 700; }
.kadia-dialog-list .vd-why { color: var(--ink-2, #4e5754); font-size: .88rem; }
@media (prefers-reduced-motion: reduce) {
  .kadia-dialog-overlay, .kadia-dialog { animation: none; }
  .kadia-dialog-list button:hover { transform: none; }
}

/* Inline, per-field error text - the other half of finding 13. Sits directly
   under the input it belongs to, so the reason is where the eye already is. */
.field-error-text {
  display: block;
  margin-top: 6px;
  color: var(--stop, #b3261e);
  font-size: .85rem;
  font-weight: 500;
}

/* ===================== standalone content pages =====================
   /about, /pricing, /faq, /contact (2026-10-01, pre-launch audit P2-1).
   Each one reuses its homepage section's own markup and rules (#how,
   #integrity, #pricing, #faq...), so only what is new lives here: the page
   heading, the closing call-to-action band and the contact layout. */
.page-intro {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  padding: 56px 0 40px;
}
.page-intro .container { max-width: 860px; }
.page-intro-kicker {
  margin: 0 0 10px;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .08em;
  color: var(--signal);
}
.page-intro h1 {
  margin: 0 0 14px;
  font-size: var(--t-3xl); font-weight: 700; line-height: 1.2;
  letter-spacing: -.02em; color: var(--ink);
  max-inline-size: 26ch; text-wrap: balance;
}
.page-intro-lead {
  margin: 0;
  font-size: var(--t-lg); line-height: 1.75; color: var(--ink-2);
  max-width: 62ch;
}

.nav-links a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--signal); }

/* a page's sections stop at the CTA band, not the homepage's gaps */
.site-page #about { background: var(--plate); padding: 64px 0; }
.site-page #pricing { padding-top: 48px; }
.site-page #faq { padding: 48px 0 56px; }
.about-attorney-label {
  margin: 0 0 2px;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em; color: var(--ink-3);
}
.about-contact-line { margin-top: 8px; font-weight: 700; }
.about-contact-line a, .pricing-page-note a { color: var(--signal); text-underline-offset: 3px; }
.pricing-page-note {
  max-width: 760px; margin: 18px auto 0;
  color: var(--ink-3); font-size: var(--t-md); text-align: center;
}
.faq-page-more { text-align: center; margin: 28px 0 0; }

.page-cta-band { background: var(--ink); color: var(--on-ink); padding: 44px 0; }
.page-cta-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px 32px; flex-wrap: wrap;
}
.page-cta-band h2 { margin: 0 0 4px; font-size: var(--t-xl); color: #fff; }
.page-cta-band p { margin: 0; color: var(--on-ink-dim); }
.page-cta-band .btn { min-height: 48px; padding-inline: 26px; }

/* ---- /contact ---- */
.contact-page { padding: 48px 0 72px; background: var(--paper); }
.contact-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px;
  gap: 28px; align-items: start;
}
.contact-grid:has(> .contact-details[hidden]) { grid-template-columns: minmax(0, 760px); justify-content: center; }
.contact-form-card { padding: 28px; }
.contact-form-card h2, .contact-details h2 { margin: 0 0 18px; font-size: var(--t-xl); color: var(--ink); }
.contact-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
.contact-form-card textarea { min-height: 140px; resize: vertical; }
.contact-form-card .btn[type="submit"] { min-height: 48px; padding-inline: 32px; }
.contact-form-card .contact-widget-error { margin-bottom: 14px; }
.contact-page-success h3 { margin: 0 0 8px; color: var(--signal); outline: none; }
.contact-page-success p { color: var(--ink-2); margin: 0 0 18px; }
.contact-details {
  background: var(--plate); border: 1px solid var(--rule); border-radius: var(--r-plate);
  padding: 24px;
}
.contact-details dl { margin: 0; display: grid; gap: 16px; }
.contact-details dt { font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em; color: var(--ink-3); margin-bottom: 2px; }
.contact-details dd { margin: 0; font-weight: 700; color: var(--ink); }
.contact-details a { color: var(--ink); }

@media (max-width: 767px) {
  .page-intro { padding: 36px 0 28px; }
  .page-intro h1 { font-size: var(--t-2xl); }
  .page-intro-lead { font-size: var(--t-base); }
  .page-cta-inner { flex-direction: column; align-items: stretch; text-align: center; }
  .contact-grid, .contact-grid:has(> .contact-details[hidden]) { grid-template-columns: 1fr; }
  .contact-form-row { grid-template-columns: 1fr; }
  .contact-form-card { padding: 20px; }
}

/* ---- /outcome: the answer page behind the outcome email (2026-10-01) ---- */
.outcome-page { max-width: 520px; margin: 56px auto 72px; padding: 0 16px; }
.outcome-card { padding: 30px 26px; outline: none; }
.outcome-card h1 { margin: 0 0 8px; font-size: var(--t-xl); color: var(--ink); text-wrap: balance; }
.outcome-sub { margin: 0 0 20px; color: var(--ink-2); line-height: 1.75; }
.outcome-loading { margin: 0; color: var(--ink-3); }
.outcome-options { border: 0; margin: 0 0 18px; padding: 0; display: grid; gap: 10px; }
.outcome-option {
  display: flex; align-items: center; gap: 12px;
  min-height: 52px; padding: 12px 16px;
  border: 1px solid var(--rule); border-radius: var(--r-ctl);
  background: var(--plate); cursor: pointer; font-weight: 500;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.outcome-option:hover { border-color: var(--signal); }
.outcome-option:has(input:checked) { border-color: var(--signal); background: var(--signal-tint); }
.outcome-option input { width: 20px; height: 20px; margin: 0; flex-shrink: 0; }
.outcome-error { margin: 0 0 14px; color: var(--stop); font-weight: 500; }
.outcome-card .btn-block { min-height: 50px; }
.outcome-actions { display: flex; gap: 12px; flex-wrap: wrap; }
.dt-outcome-ask {
  display: flex; align-items: center; justify-content: space-between; gap: 10px 16px; flex-wrap: wrap;
  margin-top: 14px; padding: 12px 14px;
  border: 1px solid var(--signal); border-radius: var(--r-card-sm); background: var(--signal-tint);
  font-weight: 700; color: var(--ink);
}
