/* This file is served under a name stamped from its own bytes, which is the
   only cache control the CDN in front of it will honour: change the file and
   the URL changes with it. It is also the way out of a poisoned edge cache,
   because a URL that never existed cannot have a stale answer stored for it. */
/* Self-hosted, so the critical path has no third-party origin on it.
 * Downloaded from Google Fonts; hebrew and latin subsets only — the site
 * renders nothing else, and the cyrillic and vietnamese cuts were four
 * more files the browser had to consider.
 * font-display: swap keeps text visible while the face loads. */
/* Heebo is served as one variable file per subset, so all four weights the
 * site uses cost two downloads rather than eight. Archivo Black is Latin only
 * because the only thing set in it is the mark. */
@font-face{font-family:'Heebo';font-style:normal;font-weight:100 900;font-display:swap;
  src:url(/assets/fonts/heebo-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:'Heebo';font-style:normal;font-weight:100 900;font-display:swap;
  src:url(/assets/fonts/heebo-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;}
@font-face{font-family:'Archivo Black';font-style:normal;font-weight:400;font-display:swap;
  src:url(/assets/fonts/archivo-black-400-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;}
@font-face{font-family:'Karantina';font-style:normal;font-weight:400;font-display:swap;
  src:url(/assets/fonts/karantina-400-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:'Karantina';font-style:normal;font-weight:400;font-display:swap;
  src:url(/assets/fonts/karantina-400-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;}
@font-face{font-family:'Karantina';font-style:normal;font-weight:700;font-display:swap;
  src:url(/assets/fonts/karantina-700-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:'Karantina';font-style:normal;font-weight:700;font-display:swap;
  src:url(/assets/fonts/karantina-700-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;}

/* ─────────────────────────────────────────────────────────────────────────
   GPT.org.il — built to the supplied design.

   Monochrome on paper, with one green that appears in exactly three places:
   the dot in the logo, a link on hover, and the "Hebrew" mark. Karantina
   carries every display size; IBM Plex Sans Hebrew carries everything a person
   actually reads. The only colour that varies is the tile behind a tool's
   initial, and it varies per tool so a grid of them reads as a set of objects
   rather than a wall.
   ───────────────────────────────────────────────────────────────────────── */
:root{
  --paper:#FAF9F6; --card:#FFFFFF; --sunk:#F0EEE8;
  --ink:#131311; --ink-2:#5B5A55; --ink-3:#8A8983;
  --line:#E5E2DA; --line-2:#EDEBE4; --line-3:#D8D4C9;
  --green:#2FA84F; --green-ink:#4C7A12;
  /* The one bright colour, and it only ever appears on the dark. */
  --lime:#B7F13F; --tint:#EEF9D6; --tint-line:#D6EFA6; --tint-ink:#3F6A0A;
  --wrap:1240px;
  --ui:'Heebo',system-ui,sans-serif;
  /* The display face for a tool's own name and for section headings. */
  --disp:Karantina,'Heebo',sans-serif;
  /* The mark, and the numbers that behave like a mark. */
  --heavy:'Archivo Black','Heebo',sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;
  color-scheme:light;
}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  --paper:#0F0F0E; --card:#191917; --sunk:#201F1D;
  --ink:#F4F3EE; --ink-2:#AEACA4; --ink-3:#8B8981;
  --line:#2A2926; --line-2:#2E2D29; --line-3:#39372F;
  --green:#4FC46F; --green-ink:#9BD84F;
  --lime:#B7F13F; --tint:#22301A; --tint-line:#33471F; --tint-ink:#C9F565;
  color-scheme:dark;
}}
:root[data-theme=dark]{
  --paper:#0F0F0E; --card:#191917; --sunk:#201F1D;
  --ink:#F4F3EE; --ink-2:#AEACA4; --ink-3:#8B8981;
  --line:#2A2926; --line-2:#2E2D29; --line-3:#39372F;
  --green:#4FC46F; --green-ink:#9BD84F;
  --lime:#B7F13F; --tint:#22301A; --tint-line:#33471F; --tint-ink:#C9F565;
  color-scheme:dark;
}
*{box-sizing:border-box}
/* A rule with display: on it beats the hidden attribute, and every element
   here that gets toggled has one. This is the line that makes el.hidden mean
   what it says, everywhere. */
[hidden]{display:none!important}
html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);
  font-family:var(--ui);-webkit-font-smoothing:antialiased}
body{direction:rtl;font-size:16px;line-height:1.6}
a{color:var(--ink);text-decoration:none}
a:hover{color:var(--green-ink)}
input,button{font-family:inherit}
input:focus{outline:none}
button{cursor:pointer}
@keyframes fadeUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
:focus-visible{outline:2px solid var(--green);outline-offset:3px;border-radius:4px}
.skip{position:absolute;right:-9999px}
.skip:focus{right:16px;top:16px;background:var(--ink);color:var(--paper);padding:10px 16px;border-radius:10px;z-index:20}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;direction:ltr;unicode-bidi:isolate}

/* header ─────────────────────────────────────────────────────────────── */
/* The header, to the supplied design ────────────────────────────────────
   Sticky, 64px, frosted, with a hairline under it and the reading progress
   riding on that line. It stays put because the categories panel hangs off
   it and because on a 1,284 word page the way back should not be a scroll
   away. */
.hdr{position:sticky;top:0;z-index:30;
  background:color-mix(in oklab,var(--paper) 82%,transparent);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border-bottom:1px solid color-mix(in oklab,var(--ink) 6%,transparent)}
.hdr__in{max-width:var(--wrap);margin:0 auto;padding:0 clamp(16px,4vw,40px);height:68px;
  display:flex;align-items:center;justify-content:space-between;gap:24px}
.hdr__act{display:flex;align-items:center;gap:10px}
/* The mark is the one place on the page that plays. Pointing at it slides the
   word a hair to the left and throws the dot up off the baseline, which is the
   whole of the animation and the reason it does not need any more. */
.mark{font-family:var(--heavy);font-weight:400;font-size:27px;line-height:1;
  letter-spacing:-.04em;display:inline-flex;align-items:baseline;gap:3px;direction:ltr}
/* The word stays black. The site turns links green on hover and the mark is a
   link, so it has to say so. */
.mark,.mark:hover{color:var(--ink)}
.mark span{display:inline-block;transition:transform .35s cubic-bezier(.2,.8,.2,1)}
.mark i{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--green);
  margin-inline-start:3px;
  transition:transform .35s cubic-bezier(.34,1.56,.64,1),background .25s ease}
.mark:hover span{transform:translateX(-2px)}
.mark:hover i{background:var(--lime);transform:translateY(-14px) scale(1.25)}
@media (prefers-reduced-motion:reduce){
  .mark span,.mark i{transition:none}
  .mark:hover span,.mark:hover i{transform:none}
}
.nav>ul{display:flex;align-items:center;gap:6px;list-style:none;margin:0;padding:0;
  font-size:15px;font-weight:500}
.nav>ul>li{position:relative}
.nav>ul>li>a{color:var(--ink);display:flex;align-items:center;gap:6px;
  padding:8px 14px;border-radius:999px;transition:background .15s ease,color .15s ease}
.nav>ul>li>a:hover{background:var(--sunk)}
/* The item that owns the open panel goes solid, so the panel reads as hanging
   off it rather than off the header. */
.nav>ul>li.has:hover>a,.nav>ul>li.has:focus-within>a,
.nav>ul>li.has.is-on>a{background:var(--ink);color:var(--paper)}
.nav>ul>li>a[aria-current]{background:var(--ink);color:var(--paper)}
.caret{display:inline-flex;width:10px;height:10px;flex:none;opacity:.55;
  transition:transform .2s ease}
.caret svg{width:10px;height:10px;display:block}
.nav>ul>li.has:hover .caret,.nav>ul>li.has:focus-within .caret,
.nav>ul>li.has.is-on .caret{transform:rotate(180deg);opacity:1}

/* The one thing the header asks for, so it is outlined rather than plain, and
   fills in on hover. */
.menu__btn{display:none;width:44px;height:44px;border-radius:50%;border:1px solid var(--line-3);
  background:var(--card);cursor:pointer;place-items:center;align-content:center;gap:4px;padding:0}
.menu__btn i{display:block;width:16px;height:2px;border-radius:2px;background:var(--ink);
  transition:transform .2s ease,opacity .2s ease}
.hdr.is-open .menu__btn i:first-child{transform:translateY(3px) rotate(45deg)}
.hdr.is-open .menu__btn i:last-child{transform:translateY(-3px) rotate(-45deg)}
.nav__cta{display:none}
.hdr__cta{padding:10px 18px;border-radius:999px;background:var(--ink);color:var(--paper);
  font-size:15px;font-weight:700;transition:background .2s ease}
.hdr__cta:hover,.hdr__cta[aria-current]{background:#2A2A27;color:var(--paper)}

/* Sub-menus. Hover or keyboard focus opens them; the links are in the served
   HTML either way, which is the half that matters for crawling. */
.sub{position:absolute;top:100%;inset-inline-start:0;padding-top:12px;
  opacity:0;visibility:hidden;transform:translateY(-4px);
  transition:opacity .16s ease,transform .16s ease,visibility .16s;z-index:15}
.nav .has:hover .sub,.nav .has:focus-within .sub{opacity:1;visibility:visible;transform:none}
.sub__in{background:var(--card);border:1px solid var(--line);border-radius:20px;
  padding:10px;box-shadow:0 22px 54px -20px rgba(0,0,0,.24)}
.sub ul{list-style:none;margin:0;padding:0;min-width:250px;display:grid;gap:1px}
.sub a{display:flex;justify-content:space-between;gap:14px;align-items:baseline;
  padding:9px 13px;border-radius:11px;font-size:14.5px;color:var(--ink-2)}
.sub a b{font-weight:500}
.sub a:hover{background:var(--sunk);color:var(--ink)}
.sub a span{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums}

/* Twelve categories, laid out as a map of the site rather than a list to
   scroll. It is anchored to the header rather than to its own nav item,
   because a three column panel hung off a 70px word ends up off the screen. */
/* Anchored to the header rather than to the viewport, so it travels with it.
   The list item goes static so the panel's containing block is the header and
   it can span the full width instead of hanging off a 70px word. The header
   needs no position of its own here: it is already sticky, and repeating
   position:relative for it silently un-stuck it. */
/* Only the full-width panel needs the header as its containing block. The
   narrow one has to stay anchored to its own word, and when it inherited this
   it hung off the edge of the screen instead. */
.nav>ul>li.has--wide{position:static}
/* Full width, and it arrives: eight pixels up and transparent, settling into
   place. Everything else in the header is still, so this is where the motion
   goes. */
.sub--wide{position:absolute;inset-inline:0;top:100%;z-index:30;background:var(--card);
  border-bottom:1px solid var(--line);box-shadow:0 40px 80px -40px rgba(19,19,17,.35);
  opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-8px);
  transition:opacity .2s ease,transform .25s cubic-bezier(.2,.8,.2,1),visibility .2s}
.nav .has:hover .sub--wide,.nav .has:focus-within .sub--wide,
.nav .has.is-on .sub--wide{opacity:1;visibility:visible;
  pointer-events:auto;transform:none}
/* The narrow one answers to the same switch, so leaving the header is what
   closes it there too. */
.nav .has.is-on>.sub{opacity:1;visibility:visible;transform:none}
@media (prefers-reduced-motion:reduce){.sub--wide{transition:opacity .2s ease,visibility .2s;transform:none}}
.sub--wide .sub__in{max-width:var(--wrap);margin:0 auto;width:100%;
  padding:28px clamp(16px,4vw,40px) 32px;border:0;border-radius:0;box-shadow:none;background:none;
  display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:32px;align-items:stretch}
.sub__main{display:flex;flex-direction:column;gap:18px;min-width:0}
.sub--wide ul{grid-template-columns:repeat(var(--cols,3),minmax(0,1fr));gap:4px 12px;min-width:0}
/* Under about a thousand pixels the panel beside the list is what breaks the
   layout: the three columns get too narrow to hold a category name on one
   line. The list is the part that matters, so the panel is what goes. */
@media(max-width:1080px){
  .sub--wide .sub__in{grid-template-columns:minmax(0,1fr);gap:0}
  .sub__side{display:none}
}
/* A name, the count under it, and a light at the end that comes on when the
   pointer is over the row. */
.sub--wide ul a{align-items:center;justify-content:space-between;gap:12px;
  padding:10px 12px;border-radius:14px;color:var(--ink);transition:background .15s ease}
.sub--wide ul a:hover{background:#F5F3EE;color:var(--ink)}
.sub--wide ul a>span{display:flex;flex-direction:column;gap:2px;min-width:0}
.sub--wide ul a>i{width:8px;height:8px;border-radius:50%;flex:none;background:var(--line);
  transition:background .15s ease,transform .15s ease}
.sub--wide ul a:hover>i{background:var(--green);transform:scale(1.15)}
.sub--wide ul a b{font-size:16px;font-weight:700;letter-spacing:-.01em;line-height:1.2;color:var(--ink)}
.sub--wide ul a>span span{font-size:12px;color:var(--ink-3)}
/* The panel beside the list says what the category you are pointing at holds.
   It carries no tool of its own, so it costs the same on eleven thousand pages
   as it does on one. */
.sub__side{background:var(--ink);color:#fff;border-radius:24px;padding:26px;
  display:flex;flex-direction:column;gap:18px;overflow:hidden}
.sub__side-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.sub__side-top b{font-size:12px;font-weight:700;color:var(--lime);letter-spacing:.04em}
.sub__side-top span{font-size:12px;color:rgba(255,255,255,.55)}
.sub__side-mid{flex:1;display:flex;flex-direction:column;justify-content:center;gap:6px;padding:8px}
.sub__side-mid b{font-weight:900;font-size:56px;letter-spacing:-.04em;line-height:1}
.sub__side-mid span{font-size:14px;color:rgba(255,255,255,.6)}
/* Once the search index is in memory the panel stops counting and starts
   naming: three tools out of the category the pointer is on. */
.sub__side-mid.is-list{justify-content:flex-start;gap:6px;padding:0}
/* Scoped past .sub a, which sets the grey the drop-down list wants and this
   panel does not. */
.sub .peek{display:flex;align-items:center;gap:12px;padding:8px;border-radius:14px;color:#fff;
  transition:background .15s ease}
.sub .peek:hover{background:rgba(255,255,255,.08);color:#fff}
.sub .peek__t{width:36px;height:36px;border-radius:10px;flex:none;display:grid;place-items:center;
  font-weight:900;font-size:15px;color:var(--ink);overflow:hidden;
  box-shadow:0 0 0 1px rgba(255,255,255,.12)}
.sub .peek__t img{width:100%;height:100%;object-fit:cover;display:block}
/* .sub a span already claims every span in a drop-down for the grey the list
   wants, and the panel's rows are spans in a drop-down. They say so louder. */
.sub .peek__w{min-width:0;display:flex;flex-direction:column;color:#fff}
.sub .peek__w b{font-size:15px;font-weight:700;direction:ltr;text-align:start;color:#fff}
.sub .peek__w span{font-size:12px;color:rgba(255,255,255,.55);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.sub__go{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 16px;border-radius:999px;background:var(--lime);color:var(--ink);
  font-size:14px;font-weight:700}
.sub__go:hover{background:#C9F565;color:var(--ink)}
.sub__go i{font-style:normal}
.sub__top{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:0 13px;font-size:12px;font-weight:700;color:var(--ink-3);letter-spacing:.04em}
.sub__top a{padding:0;font-size:13px;font-weight:600;color:var(--ink);display:inline-flex;gap:7px}
.sub__top a:hover{background:none;color:var(--green-ink)}
.sub__top i{font-style:normal;color:var(--ink-3)}
.sub__foot{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:14px 13px 0;
  border-top:1px solid var(--sunk);margin-top:auto}
.sub__foot span{font-size:12px;font-weight:700;color:var(--ink-3);margin-inline-end:4px}
.sub__foot a{padding:6px 12px;border:1px solid var(--line);border-radius:999px;
  font-size:13px;font-weight:600;color:var(--ink);background:var(--card)}
.sub__foot a.is-open{background:var(--tint);border-color:var(--tint-line);color:var(--tint-ink)}
.sub__foot a:hover{background:var(--ink);border-color:var(--ink);color:var(--paper)}
/* On a phone the header used to wrap onto three rows and take three hundred
   and fifty pixels before the page said anything. The mark and the search stay
   on one row; the navigation becomes a single scrolling strip under it, so
   every link is still in the HTML and still one tap away, in ninety pixels
   instead of three hundred and fifty. */
@media(max-width:760px){
  .hdr__in{height:64px;flex-wrap:nowrap;gap:10px}
  .hdr__right{gap:8px}
  .menu__btn{display:grid}
  .hdr__cta{display:none}
  .hdr .find__btn{width:44px;height:44px}
  /* Closed, the drawer is still in the HTML and still one tap away. Open, it is
     the header's own row: no overlay, no scroll lock, nothing to dismiss. */
  .nav{display:none;position:absolute;top:64px;inset-inline:0;background:var(--paper);
    border-top:1px solid var(--line);border-bottom:1px solid var(--line);
    padding:8px clamp(16px,4vw,40px) 16px}
  .hdr.is-open .nav{display:block}
  .nav>ul{flex-direction:column;align-items:stretch;gap:0;font-size:18px;font-weight:600}
  .nav>ul>li>a{display:block;padding:14px 0;border-radius:0;
    border-bottom:1px solid var(--line)}
  .nav>ul>li>a:hover{background:none}
  .nav>ul>li>a[aria-current]{background:none;color:var(--green-ink)}
  .nav__cta{display:block}
  .nav>ul>li.nav__cta>a{color:var(--green-ink)}
  .nav>ul>li:last-child>a{border-bottom:0}
  .sub{display:none}
  .caret{display:none}
  /* The page ends above the docked bar, because a bar that covers the last
     line of a page is a bar that eats it. */
  .page{padding-bottom:120px}
  .crumb{padding-top:14px;padding-bottom:0}
  /* The rail's own sticky top clears the header rather than hiding under it. */
  .rail{top:56px!important}
  [id]{scroll-margin-top:118px}
}

/* hero ───────────────────────────────────────────────────────────────── */
.hero{max-width:var(--wrap);margin:0 auto;padding:56px 24px 32px;display:grid;gap:22px}
.hero h1{--h1:clamp(56px,11vw,168px);margin:0;font-family:var(--disp);font-weight:700;
  font-size:var(--h1);line-height:.88;letter-spacing:.005em;
  max-width:16ch;text-wrap:balance}
.hero p.lede{margin:0;font-size:19px;color:var(--ink-2);max-width:46ch;line-height:1.5}
.hero .stats{display:flex;gap:28px;flex-wrap:wrap;margin:6px 0 0;padding:0;list-style:none}
.hero .stats b{display:block;font-family:var(--ui);font-weight:900;font-size:40px;
  line-height:1;letter-spacing:-.03em}
.hero .stats span{font-size:13px;color:var(--ink-2);font-weight:500}

/* The home page, centred ────────────────────────────────────────────────
   The heading sat at the right edge with the search field under it, which
   is the shape of an article. This is not an article, it is a place you
   arrive at to look something up, and the field belongs in the middle of
   the screen where a person's eye already is. Only the home page takes
   this; every other hero keeps its heading at the reading start. */
.hero--mid{justify-items:center;text-align:center;padding-top:clamp(56px,8vw,96px);gap:0}
/* The home heading is the heavy grotesque, not the condensed display face:
   this line is the first thing anyone sees and it is meant to read as a
   statement, not as a poster. */
.hero--mid h1{--h1:clamp(56px,9vw,124px);font-family:var(--ui);font-weight:900;
  font-size:var(--h1);line-height:.98;letter-spacing:-.035em;max-width:none;margin:36px 0 0}
.hero--mid p.lede{margin:32px 0 0;font-size:clamp(17px,1.5vw,21px);line-height:1.6;
  color:var(--ink-2);font-weight:400}
.hero--mid .find{margin-top:44px}
.hero--mid .chips{margin-top:28px}
.hero--mid p.lede{max-width:640px}
/* justify-items on the grid made the form shrink to its content and the
   field came out a third of its width. The form is centred by giving it a
   width and auto margins, not by centring its own children. */
.hero--mid .find{width:min(100%,760px);justify-self:center}
.hero--mid .chips{justify-content:center;max-width:960px}

/* The one line that says how big this is and how it was made. */
.hero__now{display:inline-flex;align-items:center;gap:9px;margin:0;padding:7px 15px;
  border-radius:999px;border:1px solid var(--line);background:var(--card);
  font-size:13px;font-weight:500;color:var(--ink-2)}
/* The pulse animates colour, not opacity or transform. Those two get the
   element promoted to its own compositor layer, and a promoted layer paints
   over the categories panel however the z-index is arranged: the dot showed
   through a solid white menu sitting two stacking levels above it. */
.dot{width:8px;height:8px;border-radius:50%;background:var(--green);flex:none;
  animation:pulse 2.6s ease-in-out infinite}
@keyframes pulse{0%,100%{background-color:var(--green)}
  50%{background-color:color-mix(in oklab,var(--green) 30%,var(--card))}}
@media (prefers-reduced-motion:reduce){.dot{animation:none}}
/* The full stop the sentence lands on, in the one colour this site owns.
   Drawn rather than set: Karantina's period at 168px is a large square that
   sits below the line and reads as a stray block rather than as punctuation. */
/* Sized from the heading's own font-size rather than from its own, because
   zeroing the font-size to hide the glyph also zeroes every em on it, and
   sitting on vertical-align:baseline is what puts it on the line instead of
   under it: Karantina's descender is deep and an absolutely positioned dot
   inside an inline box lands at the bottom of that descender. */
/* The full stop the sentence lands on, in the one colour this site owns. It
   is the glyph, not a drawn circle: that workaround existed only while the
   heading was set in Karantina, whose period at 168px is a square block. */
.dot-i{color:#7BB51C}

/* Three numbers in one bordered box read as a fact sheet; three loose
   columns read as leftovers. */
.stats--box{margin-top:clamp(28px,4vw,52px);gap:0;border:1px solid var(--line);
  border-radius:20px;background:var(--card);overflow:hidden}
.stats--box li{padding:22px clamp(24px,4vw,44px);text-align:center;
  border-inline-start:1px solid var(--line)}
.stats--box li:first-child{border-inline-start:0}
@media(max-width:560px){
  .stats--box{flex-direction:column;width:100%}
  .stats--box li{border-inline-start:0;border-top:1px solid var(--line)}
  .stats--box li:first-child{border-top:0}
}

.find{display:grid;gap:14px;max-width:760px}
.find__q{display:flex;align-items:center;gap:10px;background:var(--card);
  border:1px solid var(--line);border-radius:999px;padding:4px 6px 4px 4px}
.find__q input{flex:1;border:0;background:transparent;color:var(--ink);
  font-size:16px;padding:12px 16px;min-width:0}
.find__q .ico{width:38px;height:38px;display:grid;place-items:center;border-radius:50%;
  background:var(--ink);color:var(--paper);flex:none;border:0;cursor:pointer;
  transition:background .18s}
.find__q .ico svg{width:17px;height:17px;stroke-linecap:round}
.hero--mid .find__q .ico svg{width:20px;height:20px}
.find__q .ico:hover{background:var(--green-ink)}
/* On the home page it is the largest thing on the screen after the heading. */
.hero--mid .find__q{height:76px;padding:0 10px;gap:14px;
  box-shadow:0 24px 60px -24px rgba(19,19,17,.25),0 2px 6px rgba(19,19,17,.04)}
.hero--mid .find__q:hover{border-color:var(--ink);box-shadow:0 28px 70px -24px rgba(19,19,17,.35)}
.hero--mid .find__q input{font-size:19px;padding:0 20px}
/* The one place the bright colour appears, and it is on the dark. */
.hero--mid .find__q .ico{width:56px;height:56px;font-size:22px;color:var(--lime)}
.hero--mid .find__q .ico:hover{background:var(--ink);color:#fff}
@media(max-width:560px){
  .hero--mid .find__q{height:64px;padding:0 7px;gap:8px}
  .hero--mid .find__q input{font-size:16.5px;padding:0 14px}
  .hero--mid .find__q .ico{width:48px;height:48px;font-size:19px}
}
.chips{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0;padding:0}
.chips a{display:flex;align-items:center;gap:10px;font-size:14px;font-weight:500;
  color:var(--ink);border:1px solid var(--line);border-radius:999px;padding:9px 16px;
  background:var(--card);transition:all .15s}
.chips a:hover{border-color:var(--ink);background:var(--ink);color:var(--paper)}
.chips a[aria-current]{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.chips .n{color:var(--ink-3);font-size:12px;font-family:var(--mono);opacity:.75;margin:0}
.chips a[aria-current] .n{color:var(--line-3)}
.chips button{font:inherit;font-size:13.5px;color:var(--ink-2);border:1px solid var(--line);
  border-radius:999px;padding:8px 14px;background:var(--card);appearance:none}
.chips button:hover{border-color:var(--ink);color:var(--ink)}
.chips button[aria-pressed=true]{background:var(--ink);border-color:var(--ink);color:var(--paper)}

/* the grid ───────────────────────────────────────────────────────────── */
.band{max-width:var(--wrap);margin:0 auto;padding:16px 24px 96px;display:grid;gap:28px}
.page .band{max-width:none;margin:0;padding:0}
/* A section title is a section title. It was set at fourteen pixels next to a
   card whose name is twenty-one, which read as a label on the cards rather
   than as the heading over them. */
.band__top{display:flex;align-items:baseline;justify-content:space-between;gap:24px;
  font-size:14px;color:var(--ink-3);flex-wrap:wrap}
.band__top b{color:var(--ink);font-weight:600}
.band__h{margin:0;font-size:clamp(26px,3vw,32px);font-weight:900;letter-spacing:-.03em;
  color:var(--ink)}
.band__top>span>a{display:inline-flex;align-items:center;gap:8px;font-size:15px;font-weight:600;
  color:var(--ink);padding:8px 0;border-bottom:1px solid transparent;transition:border-color .2s ease}
.band__top>span>a:hover{border-bottom-color:var(--ink)}
#near .band__top{align-items:flex-end;border:0;padding:0;margin-bottom:4px}
#near .band__h{font-family:var(--disp);font-weight:700;font-size:clamp(44px,6vw,72px);
  line-height:.9;letter-spacing:0}
#near .band__h span{display:block;font-family:var(--ui);font-weight:400;font-size:15px;
  color:var(--ink-3);margin-top:8px}
#near .band__top>span>a{padding:10px 16px;border-radius:999px;border:1px solid var(--line-3);
  transition:background .2s ease,color .2s ease,border-color .2s ease}
#near .band__top>span>a:hover{background:var(--ink);color:var(--card);border-color:var(--ink)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px;
  list-style:none;margin:0;padding:0}
.tool{display:grid;grid-template-rows:auto 1fr auto;gap:14px;background:var(--card);
  border:1px solid var(--line);border-radius:22px;padding:24px;
  transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;
  animation:fadeUp .35s ease both}
.tool:hover{transform:translateY(-3px);border-color:var(--ink);
  box-shadow:0 30px 60px -30px rgba(19,19,17,.35)}
.tool__top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.badge{width:52px;height:52px;border-radius:14px;display:grid;place-items:center;
  font-family:var(--ui);font-weight:900;font-size:22px;letter-spacing:-.04em;color:var(--ink);
  overflow:hidden;flex:none}
.badge img{width:100%;height:100%;object-fit:cover;display:block}
img{max-width:100%;height:auto}
.price{font-size:12px;font-weight:600;color:var(--ink-2);border:1px solid var(--line);
  border-radius:999px;padding:5px 11px;white-space:nowrap}
.tool h3{margin:0;font-size:21px;font-weight:700;letter-spacing:-.02em}
.tool h3 a::after{content:"";position:absolute;inset:0}
.tool{position:relative}
.tool p{margin:8px 0 0;font-size:15px;line-height:1.6;color:var(--ink-2);text-wrap:pretty}
.tool__meta{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:auto;padding-top:14px;border-top:1px solid var(--sunk);
  font-size:13px;font-weight:500;color:var(--ink-2)}
.tool__meta .mono{font-size:12px;font-weight:400;color:var(--ink-3)}
.he{display:inline-flex;align-items:center;gap:5px;color:var(--green-ink)}
.he i{width:6px;height:6px;border-radius:50%;background:var(--green);display:inline-block}

/* breadcrumb ─────────────────────────────────────────────────────────── */
.crumb{max-width:var(--wrap);margin:0 auto;padding:22px 24px 0}
.crumb ol{display:flex;gap:9px;list-style:none;margin:0;padding:0;font-size:13px;color:var(--ink-3);flex-wrap:wrap}
.crumb li+li::before{content:"/";margin-inline-end:9px;opacity:.4}

/* tool page ──────────────────────────────────────────────────────────── */
.page{max-width:var(--wrap);margin:0 auto;padding:26px 24px 110px;display:grid;gap:34px}
/* The tool hero, to the supplied design: two equal columns that collapse at
   400px each, the content on one side and the tool's own picture on the
   other, everything centred against it. */
.lead{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,400px),1fr));
  gap:clamp(28px,4vw,64px);align-items:center;padding:clamp(28px,4vw,56px) 0 clamp(32px,4vw,56px)}
.lead>div{display:flex;flex-direction:column;gap:22px;min-width:0;container-type:inline-size}
.lead__head{display:flex;gap:clamp(14px,2vw,24px);align-items:center;flex-wrap:wrap;margin:0}
.lead__head .badge{width:clamp(64px,9vw,92px);height:clamp(64px,9vw,92px);
  border-radius:22px;font-family:var(--disp);font-weight:700;letter-spacing:0;
  font-size:clamp(34px,5vw,50px);flex:none;
  box-shadow:0 10px 30px -14px rgba(19,19,17,.35)}
/* The line above the name: what it is, what it costs, and a light that says
   the entry is alive. */
.eyebrow{display:flex;align-items:center;gap:10px;margin:0;font-size:13px;font-weight:600;
  letter-spacing:.06em;color:var(--ink-3)}
.eyebrow a{color:inherit}
.eyebrow a:hover{color:var(--ink)}
.eyebrow i{font-style:normal;opacity:.4}
/* One hundred and thirty-six pixels is right for a name of five letters and
   wrong for one of fifteen, which ran straight out of its column and over the
   picture beside it. The size is capped by what the column can hold: the
   width it has, divided by the letters there are. Karantina is condensed
   enough that two is the factor, and a name that is short is never touched by
   the cap at all. */
.lead h1{margin:0;font-family:var(--disp);font-weight:700;
  font-size:min(clamp(56px,12vw,136px),calc(100cqi / var(--n,6) * 2));
  line-height:.85;letter-spacing:-.005em;direction:ltr;text-align:start;
  min-width:0;overflow-wrap:break-word}
.lead .long{margin:0}
.lead p.long,.lead .long p{margin:0 0 14px;font-size:clamp(17px,1.5vw,20px);line-height:1.65;
  color:var(--ink-2);max-width:56ch}
.lead .long p:last-child{margin-bottom:0}
.lead .uses{margin:0}
.lead__cta{display:flex;flex-wrap:wrap;gap:12px;align-items:center;padding-top:6px}
.uses{display:flex;flex-wrap:wrap;gap:7px;list-style:none;margin:0 0 20px;padding:0}
.uses li{font-size:13px;font-weight:500;color:var(--ink);background:var(--card);
  border:1px solid var(--line-3);border-radius:999px;padding:7px 14px}
.go{display:inline-flex;align-items:center;gap:10px;background:var(--ink);color:var(--paper);
  font-size:17px;font-weight:600;border-radius:999px;padding:16px 26px;
  box-shadow:0 16px 36px -16px rgba(19,19,17,.6);transition:transform .2s,box-shadow .2s}
.go:hover{color:var(--paper);transform:translateY(-2px);box-shadow:0 22px 40px -16px rgba(19,19,17,.7)}
/* The arrow rides in its own green disc, the way the design has it. */
.go__arw{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--green);color:#fff;font-size:13px;font-style:normal;direction:ltr}
.go--ghost{background:transparent;color:var(--ink);border:1px solid var(--line-3);
  font-weight:500;font-size:16px;padding:15px 22px;box-shadow:none}
.go--ghost:hover{background:var(--card);color:var(--ink);box-shadow:none}
/* Edge to edge on a phone, because a button that is the reason the page exists
   should not be a small target floating at one side of it. */
@media(max-width:640px){.go{display:flex;width:100%;justify-content:center;padding:16px 24px;font-size:16px}}

.gallery{display:grid;gap:10px}
/* The width/height attributes on the <img> are a presentational hint, and an
   explicit height beats aspect-ratio — so height:auto has to be said out loud
   or every screenshot renders 800px tall and the page falls apart. */
.gallery img{width:100%;height:auto;display:block;border-radius:22px;border:1px solid var(--line-2);
  background:var(--sunk);aspect-ratio:1200/630;object-fit:cover;object-position:top center}
.gallery .two{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.gallery .two img{aspect-ratio:1200/630;border-radius:16px}
.lead:has(.gallery){align-items:start}
.lead>div:only-child{grid-column:1/-1}
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:24px;overflow:hidden}
.facts>div{background:var(--card);padding:20px 20px 18px;display:flex;flex-direction:column;
  gap:10px;min-width:0;container-type:inline-size}
/* Five facts in a two-column grid leave one cell empty, and an empty cell in
   this grid is not blank, it is the border colour showing through. */
@media(max-width:560px){.facts>div:nth-child(odd):last-child{grid-column:1/-1}}
.facts dt{font-size:12px;color:var(--ink-3);letter-spacing:.04em;margin:0}
/* break-word rather than anywhere, so the <wbr> the build puts after every
   dot is preferred over a break in the middle of a label. */
.facts dd{margin:0;font-size:18px;font-weight:600;overflow-wrap:break-word}
/* A host name is anything from eight characters to thirty-one, and a quarter
   of the card is not enough for the long ones: they were breaking in the
   middle of a word, which is the one thing a web address must never do. The
   size is capped by the cell, the same way the tool's name is capped by its
   column. */
.facts dd.mono{font-size:clamp(11px,calc(100cqi / var(--n,10) * 1.55),15px);letter-spacing:-.01em}
/* What the tool says about itself.
   It was a bordered note that read like a caption, which is the wrong weight
   for the one paragraph on the page written by somebody else. Set as a dark
   card it is unmistakably a quotation, and the visual break also does the work
   of saying "these are not our words" before anybody reads the attribution. */
.self{position:relative}
.quote{position:relative;z-index:1;margin:0;max-width:none;background:var(--ink);
  color:var(--paper);border-radius:22px;padding:26px 30px;overflow:hidden}
.quote p{margin:0;font-size:clamp(16px,1.5vw,19px);line-height:1.6;color:var(--paper)}
.quote cite{display:block;margin-top:14px;font-size:12.5px;font-style:normal;
  color:color-mix(in oklab,var(--paper) 62%,transparent)}
.quote cite .mono{color:inherit}
/* Drawn by the card rather than marked up, so it can never be read aloud
   before the quotation it decorates. */
.quote::before{content:"”";position:absolute;top:-46px;inset-inline-end:22px;pointer-events:none;
  font-family:var(--disp);font-weight:700;font-size:180px;line-height:1;
  color:color-mix(in oklab,var(--paper) 11%,transparent)}
@media(max-width:560px){.quote{padding:22px}.quote::before{font-size:130px;top:-32px}}
h2.sec{font-family:var(--disp);font-weight:700;font-size:clamp(44px,6vw,72px);
  line-height:.9;margin:0 0 22px}
.prose p{max-width:62ch;line-height:1.7;color:var(--ink-2);margin:0 0 14px}
/* On a tool page the text column is the design's own 760px, not a character
   count: at 62ch the words stopped two thirds of the way across a column that
   went on without them, and the display headings broke across two lines. */
.page__main>.prose{max-width:760px}
.page__main .prose p,.page__main .faq p{max-width:none;font-size:clamp(17px,1.4vw,19px);
  line-height:1.8;margin:0 0 26px}
.page__main .prose p:last-child,.page__main .faq p:last-child{margin-bottom:0}
.faq details{border-bottom:1px solid var(--line);padding:18px 0}
.faq summary{display:flex;justify-content:space-between;gap:16px;align-items:center;
  cursor:pointer;font-size:17px;font-weight:500;list-style:none}
.faq summary::-webkit-details-marker{display:none}
.faq__mark{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
  background:var(--sunk);color:var(--ink-2);font-size:19px;font-weight:400;line-height:1;
  transition:transform .25s ease,background .25s ease,color .25s ease}
.faq summary:hover .faq__mark{background:var(--line)}
.faq details[open] .faq__mark{transform:rotate(45deg);background:var(--ink);color:var(--paper)}
.faq p{margin:12px 0 0;color:var(--ink-2);line-height:1.7;max-width:62ch}

/* footer ─────────────────────────────────────────────────────────────── */
.ftr{border-top:1px solid var(--line);background:var(--card)}
.ftr__in{max-width:var(--wrap);margin:0 auto;padding:40px 24px;display:grid;
  grid-template-columns:1.4fr 1fr 1fr 1fr;gap:28px}
@media(max-width:820px){.ftr__in{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.ftr__in{grid-template-columns:1fr}}
.ftr p{color:var(--ink-2);font-size:14px;line-height:1.6;margin:12px 0 0;max-width:40ch}
.ftr h3{font-size:12.5px;font-weight:600;letter-spacing:.06em;color:var(--ink-3);margin:0 0 12px}
.ftr ul{list-style:none;margin:0;padding:0;display:grid;gap:9px;font-size:14.5px}
.ftr a{color:var(--ink-2)}
.ftr__btm{border-top:1px solid var(--line)}
.ftr__btm div{max-width:var(--wrap);margin:0 auto;padding:18px 24px;display:flex;
  justify-content:space-between;gap:16px;font-size:13px;color:var(--ink-3);flex-wrap:wrap}
.note{font-size:12.5px;color:var(--ink-3);line-height:1.6}

/* ═════════════════════════════════════════════════════════════════════════
   Motion.

   Three things, and each one is doing a job rather than decorating: the search
   comes forward so the page behind it stops competing for attention; a tool's
   logo and name travel from the card you clicked to the page you land on, so
   2,424 separate documents read as one place; and a grid arrives in the order
   you would read it. Everything here is switched off under
   prefers-reduced-motion, at the bottom of the file.
   ═════════════════════════════════════════════════════════════════════════ */

::selection{background:oklch(90% 0.09 145);color:var(--ink)}

/* ── page-to-page, without becoming a single-page app ────────────────────
   The whole reason this site is 2,424 files is that a crawler can read them.
   A view transition is the part of an SPA that was worth having, and it costs
   one at-rule and no JavaScript. Browsers without it simply navigate. */
@view-transition{navigation:auto}
::view-transition-old(root){animation:vtOut .18s ease both}
::view-transition-new(root){animation:vtIn .28s ease both}
@keyframes vtOut{to{opacity:0}}
@keyframes vtIn{from{opacity:0;transform:translateY(6px)}}
/* Scoped to the header: a view-transition-name has to be unique in the
   document, and the mark also appears in the footer. */
.hdr .mark{view-transition-name:mark}
.hdr .nav{view-transition-name:nav}
/* The names on a card are assigned by search.js at the moment of the click —
   a name has to be unique on the page, and there are 299 cards. */
.lead__head .badge{view-transition-name:tool-badge}
.lead h1{view-transition-name:tool-title}
::view-transition-group(tool-badge),::view-transition-group(tool-title){
  animation-duration:.42s;animation-timing-function:cubic-bezier(.2,.85,.25,1)}

/* ── the grid arrives in reading order ──────────────────────────────────── */
.grid>li{animation:fadeUp .4s cubic-bezier(.2,.8,.2,1) both;
  animation-delay:calc(var(--i,0) * 26ms)}
.tool:hover .badge{transform:scale(1.06)}
.badge{transition:transform .18s cubic-bezier(.2,.8,.2,1)}

/* Sections fade in as they enter the viewport, with no scroll listener and no
   IntersectionObserver — the browser drives it off the scroll position. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion:no-preference){
    .band__top,.facts,.faq,.quote,.prose{
      animation:riseIn linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 42%}
  }
}
@keyframes riseIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* ── the search, coming forward ─────────────────────────────────────────── */
.find__q{cursor:text;transition:border-color .18s ease,box-shadow .18s ease}
.find__q:hover{border-color:var(--line-3)}
.find__q .kbd{font-family:var(--mono);font-size:11px;color:var(--ink-3);direction:ltr;
  border:1px solid var(--line);border-radius:7px;padding:3px 7px;margin-inline-end:6px}
.hero--mid .find__q .kbd{font-size:12px;color:var(--ink-2);background:var(--paper);
  border-radius:8px;padding:5px 9px;margin-inline-end:0}
@media(max-width:640px){.find__q .kbd{display:none}}

/* A round button in the header, on every page — the overlay has to be
   reachable where there is no hero to click. */
.hdr .find__btn{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;flex:none;
  border:1px solid var(--line-3);background:var(--card);color:var(--ink);cursor:pointer;
  transition:border-color .18s,color .18s}
.hdr .find__btn svg{width:16px;height:16px;stroke-linecap:round}
.hdr .find__btn:hover{border-color:var(--ink)}

#spot{position:fixed;inset:0;z-index:60}
#spot[hidden]{display:none!important}
#spot .veil{position:absolute;inset:0;background:color-mix(in oklab,var(--paper) 62%,transparent);
  backdrop-filter:blur(18px) saturate(1.15);-webkit-backdrop-filter:blur(18px) saturate(1.15);
  opacity:0;transition:opacity .28s ease}
#spot.on .veil{opacity:1}
#spot .box{position:absolute;top:11vh;left:50%;transform:translateX(-50%);
  width:min(720px,calc(100vw - 32px));display:grid;gap:14px;
  transform-origin:top center;will-change:transform,opacity}
#spot .find__q{background:var(--card);border-color:var(--line-3);
  box-shadow:0 30px 70px -30px rgba(0,0,0,.32)}
#spot .find__q input{font-size:19px;padding:16px 18px}
#spot .modes{display:flex;gap:8px;align-items:center;justify-content:space-between}
#spot .modes .chips{margin:0}
#spot .hint{font-size:12.5px;color:var(--ink-3)}
#spot .out{background:var(--card);border:1px solid var(--line);border-radius:22px;
  max-height:min(56vh,540px);overflow:auto;overscroll-behavior:contain;
  box-shadow:0 30px 70px -34px rgba(0,0,0,.28)}
#spot .out:empty{display:none}
#spot ul{list-style:none;margin:0;padding:8px}
#spot a{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;
  padding:11px 13px;border-radius:15px}
#spot a:hover,#spot li.at>a{background:var(--sunk)}
#spot .badge{width:38px;height:38px;border-radius:11px;font-size:22px}
#spot b{display:block;font-size:15.5px;font-weight:600}
#spot span.d{display:block;font-size:13px;color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#spot span.c{font-size:12px;color:var(--ink-3);white-space:nowrap}
#spot .none{padding:30px 26px}
#spot .none h2{font-family:var(--disp);font-weight:700;font-size:38px;line-height:.95;margin:0 0 8px}
#spot .none p{margin:0;color:var(--ink-2);font-size:15px;max-width:44ch}

@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  .grid>li{animation:none}
  .badge{transition:none}
  #spot .veil{transition:none;opacity:1}
}

/* ── the pager ─────────────────────────────────────────────────────────── */
.pager{margin-top:8px}
.pager .gap{color:var(--ink-3);padding:8px 2px;align-self:center}
.pager a{min-width:42px;text-align:center}

/* ── what the search shows before a key is pressed ─────────────────────── */
#spot .hints{padding:18px 20px;display:grid;gap:14px}
#spot .hints h3{margin:0;font-size:12px;font-weight:600;letter-spacing:.06em;color:var(--ink-3)}
#spot .hints .chips{margin:0}
#spot em{font-style:normal;background:oklch(92% 0.08 145);border-radius:4px;padding:0 2px;
  box-decoration-break:clone;-webkit-box-decoration-break:clone}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) #spot em{background:oklch(38% 0.09 145);color:var(--ink)}}
:root[data-theme=dark] #spot em{background:oklch(38% 0.09 145);color:var(--ink)}
/* The browser's own clear button fights the design; the field has its own. */
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration{-webkit-appearance:none;appearance:none}

/* ── the price points, as they were read ───────────────────────────────── */
.prices{display:flex;flex-wrap:wrap;gap:8px;margin:4px 0 12px}
.prices .tag{font-size:13.5px;color:var(--ink);border:1px solid var(--line);
  border-radius:999px;padding:7px 14px;background:var(--card)}
.prices .tag.free{border-color:var(--green);color:var(--green-ink)}
.long p{margin:0 0 14px;font-size:17.5px;line-height:1.62;color:var(--ink-2);max-width:56ch}
.long p:last-child{margin-bottom:18px}

/* ── rating ────────────────────────────────────────────────────────────
   The score sits where a Hebrew reader's eye starts, and the stars fill from
   the right like everything else on the page. The disclosure is real and
   necessary, and it is folded away rather than allowed to be the largest
   thing in the block. */
.rate{border:1px solid var(--line);border-radius:24px;background:var(--card);position:relative;
  padding:clamp(20px,2.5vw,28px);box-shadow:0 1px 2px rgba(19,19,17,.04)}
.rate__main{display:flex;align-items:center;flex-wrap:wrap;gap:clamp(14px,2vw,20px);margin-top:18px}
.rate__now{display:flex;flex-direction:column;gap:2px;min-width:92px}
.rate__now b{font-family:var(--disp);font-weight:700;font-size:64px;line-height:.9;
  color:var(--ink);direction:ltr}
.rate__now b.rate__none{color:#B5B3AC}
.rate__now span{font-size:13px;color:var(--ink-3)}
.rate__div{width:1px;align-self:stretch;background:var(--line)}
.rate__ask{display:flex;flex-direction:column;gap:8px}
.rate__stars{display:flex;gap:4px}
.rate__stars button{font:inherit;font-size:34px;line-height:1;background:none;border:0;
  width:44px;height:44px;padding:0;color:var(--line-3);cursor:pointer;
  transition:color .15s ease,transform .15s ease}
/* Hovering a star lights it and every star to its right, which in this
   direction is every star below it. */
.rate__stars button:hover,.rate__stars button:hover ~ button,
.rate__stars button.on{color:#F2B41C}
.rate__stars button:hover{transform:scale(1.12)}
.rate__stars button:focus-visible{outline:2px solid var(--green);outline-offset:2px;border-radius:8px}
.rate__say{font-size:13px;color:var(--ink-3);margin:0;min-height:1.2em}
.rate__say.is-good{color:var(--green-ink)}
.rate__say.is-bad{color:oklch(52% 0.18 25)}
.rate__go{margin-inline-start:auto;display:inline-flex;align-items:center;gap:8px;min-height:44px;
  padding:11px 18px;border-radius:999px;border:1px solid var(--line-3);background:var(--card);
  font:inherit;font-size:14px;font-weight:600;color:var(--ink);cursor:pointer;
  transition:background .2s ease,color .2s ease,border-color .2s ease}
.rate__go:hover{background:var(--ink);color:var(--card);border-color:var(--ink)}
.rate__btn{margin-top:12px}
/* The toggle belongs on the title row and the answer belongs at the foot of
   the card, and a <details> holds them in one order. Lifting the summary out
   of the flow puts it where the design has it without asking JavaScript to
   open anything. */
.rate__how>summary{position:absolute;top:clamp(20px,2.5vw,28px);
  inset-inline-end:clamp(20px,2.5vw,28px);display:flex;align-items:center;gap:6px;
  min-height:22px;cursor:pointer;list-style:none;font-size:13px;color:var(--ink-3)}
.rate__how>summary::-webkit-details-marker{display:none}
.rate__how>summary:hover{color:var(--ink)}
.rate__how>summary span{display:inline-grid;place-items:center;width:20px;height:20px;
  border-radius:50%;border:1px solid var(--line-3);font-size:13px;line-height:1;
  transition:transform .2s ease}
.rate__how[open]>summary span{transform:rotate(45deg)}
.rate__how[open]{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.rate__how p{margin:0 0 10px;font-size:14px;line-height:1.65;color:var(--ink-2);max-width:64ch}
.rate__how p:last-child{margin-bottom:0}
/* Stacking the card on a phone puts the stars first and the score beside them,
   because a heading that names a score should not arrive after it. */
@media(max-width:560px){
  .rate{padding:20px}
  .rate__main{gap:14px}
  .rate__div{display:none}
  .rate__now{order:2;flex-direction:row;align-items:baseline;gap:8px}
  .rate__now b{font-size:34px;line-height:1}
  .rate__ask{order:1}
  .rate__go{order:3;margin-inline-start:0;width:100%;justify-content:center}
  /* With no ratings yet there is nothing to show here: a dash and the words
     "עוד לא דורג" repeat what the line under the name and the prompt beside the
     stars both already say, and on a phone that is a third of the card spent
     saying nothing three times. */
  .rate__now:has(.rate__none){display:none}
}

/* ── the rail ──────────────────────────────────────────────────────────
   A tool page is 500+ words across seven sections now, and the column beside
   the text was empty. This puts the outline where the eye already has nothing
   to do, and it disappears entirely below the width where it would compete. */
.page__body{display:grid;grid-template-columns:minmax(0,1fr) 240px;gap:clamp(28px,5vw,80px);align-items:start}
/* The rail comes first in the DOM so a screen reader meets the outline before
   the text. Without saying which column each one occupies, that order put the
   rail in the wide track and squeezed the article into 190px. */
/* Both belong to the first row. Naming only the column let auto-placement put
   the article on row two — the rail comes first in the DOM and claims column
   two, and a later item asking for column one cannot go backwards in the same
   row. That is why the text started 336px below its own heading, and why the
   sticky rail was trapped in a 284px row and scrolled away at once. */
.page__main{grid-column:1;grid-row:1;display:grid;gap:34px;min-width:0}
.rail{grid-column:2;grid-row:1;position:sticky;top:84px;align-self:start;
  max-height:calc(100vh - 52px);overflow:auto;overscroll-behavior:contain}
.rail h2{margin:0 0 10px;font-size:11.5px;font-weight:600;letter-spacing:.08em;color:var(--ink-3)}
.rail ol{list-style:none;margin:0;padding:0;display:grid;gap:1px;
  border-inline-start:1px solid var(--line)}
/* The padding was physical, so in a right-to-left column all of it landed on
   the side the rule is not, and every line in the list leaned against it. */
.rail a{display:block;padding:7px 0;padding-inline-start:16px;font-size:13.5px;
  color:var(--ink-2);margin-inline-start:-1px;border-inline-start:1px solid transparent}
.rail a:hover{color:var(--ink);border-inline-start-color:var(--ink)}
.rail a[aria-current]{color:var(--ink);border-inline-start-color:var(--green)}
/* On a phone the rail was simply switched off, which left the longest pages on
   the site with no way to jump and no sense of what was below. It is the same
   list and the same scroll-spy; laid sideways it costs one row and sticks
   under the top of the screen, so the section you are in is always named. */
@media(max-width:960px){
  .page__body{grid-template-columns:1fr;gap:0}
  .page__main{grid-column:1;grid-row:2}
  /* No negative margins. A grid item wider than its column makes the whole
     page scroll sideways, and on a phone that reads as the layout collapsing
     rather than as a strip you can push. */
  /* min-width:0, or the grid item takes its content's width and the whole
     page scrolls sideways: a grid child defaults to min-width:auto, which an
     overflowing flex row is happy to grow into. */
  .rail{grid-column:1;grid-row:1;min-width:0;position:sticky;top:0;z-index:30;max-height:none;overflow:visible;
    margin:0 0 22px;padding:10px 0 9px;background:color-mix(in oklab,var(--paper) 92%,transparent);
    backdrop-filter:saturate(160%) blur(12px);border-bottom:1px solid var(--line)}
  .rail h2{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);margin:0}
  .rail ol{display:flex;min-width:0;gap:8px;border:0;overflow-x:auto;padding:0;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
    -webkit-mask-image:linear-gradient(to left,#000 calc(100% - 24px),transparent);
    mask-image:linear-gradient(to left,#000 calc(100% - 24px),transparent)}
  .rail ol::-webkit-scrollbar{display:none}
  .rail li{flex:none}
  .rail a{margin:0;padding:9px 14px;border:1px solid var(--line-2);border-radius:999px;
    white-space:nowrap;font-size:14px;background:var(--card)}
  .rail a[aria-current]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
  [id]{scroll-margin-top:64px}
}
/* Anchored sections should not land under the sticky header on a jump. */
[id]{scroll-margin-top:92px}

/* ── writing a review ──────────────────────────────────────────────────── */
.rate__write{margin-top:16px;display:grid;gap:8px;max-width:52ch}
.rate__label{font-size:12.5px;color:var(--ink-3)}
.rate__text{font:inherit;font-size:15px;line-height:1.55;color:var(--ink);background:var(--paper);
  border:1px solid var(--line);border-radius:14px;padding:12px 14px;resize:vertical;min-height:76px}
.rate__text:focus{outline:none;border-color:var(--ink)}
.rate__row{display:flex;align-items:center;gap:12px}
.rate__send{font:inherit;font-size:14.5px;font-weight:500;border:0;cursor:pointer;
  background:var(--ink);color:var(--paper);border-radius:999px;padding:10px 22px}
.rate__send:hover{background:var(--green-ink)}
.rate__count{font-family:var(--mono);font-size:12px;color:var(--ink-3)}

/* ── what people wrote ─────────────────────────────────────────────────── */
.rate__list{list-style:none;margin:18px 0 0;padding:16px 0 0;border-top:1px solid var(--line)}
.rate__list li{padding:0 0 14px;margin-bottom:14px;border-bottom:1px solid var(--line)}
.rate__list li:last-child{border-bottom:0;padding-bottom:0;margin-bottom:0}
.rate__who{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:5px}
.rate__who b{font-size:14.5px;font-weight:600}
.rate__who time{font-size:12px;color:var(--ink-3)}
.rate__mini{font-size:13px;color:oklch(74% 0.16 78);letter-spacing:1px}
.rate__mini i{color:var(--line-3);font-style:normal}
.rate__list p{margin:0;font-size:15px;line-height:1.6;color:var(--ink-2);max-width:62ch;text-wrap:pretty}

/* ── the article and its byline ────────────────────────────────────────── */
.article .byline{display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;
  font-size:14px;color:var(--ink-3);margin:0 0 26px}
.article>.sec{margin-bottom:18px}
/* The date is set left to right, so a separator placed at the start of it
   lands on its left, which in this line is after it. The dot belongs to the
   item before instead, where the direction is the line's own. */
.article .byline>*:not(:last-child)::after{content:'·';margin-inline-start:20px;opacity:.4}
.byline__who{display:flex;align-items:center;gap:10px}
.byline__av{width:36px;height:36px;border-radius:50%;background:var(--ink);color:var(--card);
  display:grid;place-items:center;font-style:normal;font-weight:700;font-size:14px}
.article .byline a{color:var(--ink);font-weight:600;
  border-bottom:1px solid color-mix(in oklab,var(--ink) 25%,transparent)}
.article .byline a:hover{color:var(--green-ink)}
.article p{font-size:17px;line-height:1.75;color:var(--ink-2);max-width:64ch;margin:0 0 18px}
.page__main .article p:first-of-type{font-size:clamp(20px,1.7vw,24px);line-height:1.55;
  font-weight:500;color:var(--ink)}
.article p:first-of-type{font-size:18.5px;color:var(--ink);line-height:1.7}
.article p:last-child{margin-bottom:0}

/* ── the author page ───────────────────────────────────────────────────── */
.who{display:grid;grid-template-columns:auto minmax(0,1fr);gap:26px;align-items:start}
@media(max-width:640px){.who{grid-template-columns:1fr}}
.who__mark{width:96px;height:96px;border-radius:28px;display:grid;place-items:center;
  font-family:var(--disp);font-weight:700;font-size:52px;color:var(--ink);
  background:oklch(90% 0.06 145)}
.who__links{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:16px 0 0;padding:0}

/* The docked action ─────────────────────────────────────────────────────────
   On a phone the button that opens the tool is one screen from the top and
   everything else is below it, so by the time somebody has read enough to want
   it, it is two thousand words away. This brings it back once it has scrolled
   out of sight. It exists on phones only; on a desktop the rail already keeps
   the page in reach. */
.dock{position:fixed;inset-inline:0;bottom:0;z-index:60;display:none;gap:10px;
  align-items:center;padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  background:color-mix(in oklab,var(--paper) 90%,transparent);
  backdrop-filter:saturate(160%) blur(14px);border-top:1px solid var(--line)}
.dock .go{flex:1;justify-content:center;padding:15px 20px;font-size:16px;min-height:48px;
  box-shadow:none}
.dock .go:hover{transform:none}
/* The score rides beside it, because that is the other half of the decision. */
.dock__score{flex:none;display:flex;flex-direction:column;align-items:center;padding:0 6px;
  font-size:11px;color:var(--ink-3)}
.dock__score b{font-family:var(--disp);font-weight:700;font-size:26px;line-height:1;
  color:var(--ink);direction:ltr}
@media(max-width:760px){
  .dock.is-on{display:flex}
  body:has(.dock.is-on){padding-bottom:88px}
}

/* How far through this is ─────────────────────────────────────────────────
   The median tool page runs to 1,282 words, and a page that long owes the
   reader an answer to "how much is left". It sits above the header rather
   than inside it so it never moves the chrome, and it is decoration: it
   carries no information a screen reader needs. */
.read{position:absolute;inset-inline:0;bottom:-1px;height:2px;pointer-events:none}
.read i{display:block;height:100%;width:0;background:var(--green);
  transform-origin:left center;transition:width .1s linear}
@media (prefers-reduced-motion:reduce){.read i{transition:none}}

/* Previous and next ───────────────────────────────────────────────────────
   Two small chips at the foot of two thousand words are a full stop. A named
   panel on each side is an invitation, and it is the same link. */
.around{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
  gap:12px;margin-top:clamp(28px,4vw,52px)}
.around__a{display:flex;flex-direction:column;gap:7px;padding:20px 24px;border-radius:22px;
  border:1px solid var(--line);background:var(--card);transition:background .2s,color .2s,border-color .2s}
.around__a span{font-size:12px;letter-spacing:.06em;color:var(--ink-3);transition:color .2s}
.around__a b{display:flex;align-items:center;gap:10px;font-size:clamp(17px,1.6vw,21px);font-weight:700}
.around__a i{font-style:normal;color:var(--ink-3);transition:color .2s}
.around__a--next{align-items:flex-end;text-align:end}
.around__a:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.around__a:hover span,.around__a:hover i{color:color-mix(in oklab,var(--paper) 65%,transparent)}

/* The section that earns the page ─────────────────────────────────────────
   "What to check before committing" is the only part of a tool page its own
   marketing would never write, so it is the one section given a mark of its
   own instead of reading like every other heading. */
#check{border-inline-start:3px solid var(--green);padding-inline-start:clamp(18px,2vw,26px)}

/* The rating and the facts share one row ─────────────────────────────────
   Two cards of equal weight side by side, each falling to full width at
   320px, exactly as the design lays them out. */
.pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:16px}
.pair>.rate,.pair>.facts{margin:0}
/* Three across and the address on a row of its own, because a host name is
   the one value here with no upper bound: a quarter of the card holds
   "cursor.com" and loses "imaginator.developer-service.io" halfway through.
   Narrower than this it is two across, where the last cell is the only one
   that needs the full row to keep the border colour from showing through. */
.pair>.facts{grid-template-columns:repeat(2,minmax(0,1fr))}
.pair>.facts>div:last-child{grid-column:1/-1}
@media(min-width:1240px){
  .pair>.facts{grid-template-columns:repeat(3,minmax(0,1fr))}
  .pair>.facts>div:nth-child(4){grid-column:1/-1}
}
.rate__head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:22px 26px 0}
.rate__head h2{margin:0;font-size:15px;font-weight:700;letter-spacing:.02em}
@media(max-width:560px){.rate__head{padding:20px 20px 0}}

/* ── a model page ──────────────────────────────────────────────────────────
   A model is not a tool and does not read like one. What a person wants is
   the numbers, the files and the one line they have to run, and the design
   puts all three where the eye lands first: a dark card that states the
   figures, then the detail, with everything you would actually click kept in
   a column that follows you down the page. */
.mdl{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:24px;align-items:start;
  padding:28px 0 0}
.mdl__main{min-width:0;display:flex;flex-direction:column;gap:40px}
.mdl__hero{background:var(--ink);color:#fff;border-radius:28px;padding:clamp(22px,3vw,36px);
  display:flex;flex-direction:column;gap:28px;min-width:0}
.mdl__top{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;flex-wrap:wrap}
.mdl__id{display:flex;align-items:center;gap:18px;min-width:0;flex:1 1 100%}
.mdl__id>div{min-width:0;flex:1}
.mdl__tile{width:72px;height:72px;border-radius:20px;flex:none;display:grid;place-items:center;
  font-family:var(--heavy);font-weight:400;font-size:30px;letter-spacing:-.04em;color:#fff}
.mdl__name{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.mdl h1{margin:0;font-family:var(--heavy);font-weight:400;letter-spacing:-.035em;line-height:1;
  direction:ltr;text-align:start;
  font-size:min(clamp(22px,3.6vw,42px),calc(100cqi / var(--n,10) * 2))}
.mdl__open{font-size:12px;font-weight:700;padding:5px 11px;border-radius:999px;
  background:var(--lime);color:var(--ink)}
/* Each item is isolated: three LTR runs joined by a neutral separator get
   reordered as one group by the bidi algorithm, which put the licence and the
   date the wrong way round. */
.mdl__by{margin:8px 0 0;font-size:14px;color:rgba(255,255,255,.6);display:flex;gap:8px;
  align-items:center;flex-wrap:wrap}
.mdl__by>span{unicode-bidi:isolate}
.mdl__by>span:not(:last-child)::after{content:'·';margin-inline-start:8px;opacity:.5}
.mdl__by a{color:rgba(255,255,255,.75)}
.mdl__by a:hover{color:#fff}
.mdl__tags{display:flex;gap:8px;flex-wrap:wrap;list-style:none;margin:0;padding:0}
.mdl__tags li{font-family:var(--mono);font-size:12px;padding:6px 11px;border-radius:999px;
  border:1px solid rgba(255,255,255,.18);color:rgba(255,255,255,.8);direction:ltr}
.mdl__lede{margin:0;font-size:18px;line-height:1.6;color:rgba(255,255,255,.82);max-width:720px}
.mdl__stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:12px;
  list-style:none;margin:0;padding:0}
.mdl__stats li{padding:16px 18px;border-radius:18px;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.08)}
.mdl__stats b{display:block;font-family:var(--heavy);font-weight:400;font-size:26px;
  letter-spacing:-.03em;line-height:1;direction:ltr;text-align:start}
.mdl__stats span{display:block;margin-top:6px;font-size:12px;color:rgba(255,255,255,.55);font-weight:500}

/* The tabs are radio buttons, so every panel is in the HTML whether it is on
   screen or not, and the page needs no script to change which one is. */
.tabs{display:flex;flex-direction:column;gap:28px}
.tabs>input{position:absolute;opacity:0;pointer-events:none}
.tabs__bar{display:flex;gap:4px;border-bottom:1px solid var(--line);overflow-x:auto;
  scrollbar-width:none}
.tabs__bar::-webkit-scrollbar{display:none}
.tabs__bar label{padding:12px 18px;font-size:15px;font-weight:500;color:var(--ink-3);
  border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;cursor:pointer;
  transition:color .15s ease,border-color .15s ease}
.tabs__bar label:hover{color:var(--ink)}
.tabs__panel{display:none;flex-direction:column;gap:40px}
.tabs>input:nth-of-type(1):checked~.tabs__bar label:nth-of-type(1),
.tabs>input:nth-of-type(2):checked~.tabs__bar label:nth-of-type(2),
.tabs>input:nth-of-type(3):checked~.tabs__bar label:nth-of-type(3),
.tabs>input:nth-of-type(4):checked~.tabs__bar label:nth-of-type(4){color:var(--ink);font-weight:700;
  border-bottom-color:var(--ink)}
.tabs>input:nth-of-type(1):checked~.tabs__panel:nth-of-type(1),
.tabs>input:nth-of-type(2):checked~.tabs__panel:nth-of-type(2),
.tabs>input:nth-of-type(3):checked~.tabs__panel:nth-of-type(3),
.tabs>input:nth-of-type(4):checked~.tabs__panel:nth-of-type(4){display:flex}
.tabs>input:focus-visible~.tabs__bar label{outline:none}
.mdl h2{margin:0 0 14px;font-size:26px;font-weight:900;letter-spacing:-.03em}
/* The FAQ block is shared with the tool pages, where its heading is a display
   line broken over two rows. In a tab panel it has to match the headings
   beside it, so it borrows theirs. */
.mdl .faq .sec{font-family:var(--ui);font-weight:900;font-size:26px;letter-spacing:-.03em;
  line-height:1.2;margin:0 0 4px}
.mdl .faq .sec br{display:none}
.mdl__p{margin:0;font-size:17px;line-height:1.7;color:#3D3C38;max-width:720px}
.mdl__uses{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;
  list-style:none;margin:0;padding:0}
.mdl__uses li{background:var(--card);border:1px solid var(--line);border-radius:20px;padding:20px}
.mdl__uses b{display:block;font-size:16px;font-weight:700;letter-spacing:-.01em}
.mdl__uses p{margin:6px 0 0;font-size:14px;line-height:1.6;color:var(--ink-2)}

/* The family: the same model at other sizes, and what came after it. */
.fam{background:var(--card);border:1px solid var(--line);border-radius:24px;padding:22px;
  display:flex;flex-direction:column;gap:12px}
.fam a{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;align-items:center;
  padding:10px 12px;border-radius:14px;transition:background .15s ease}
.fam a:hover{background:var(--sunk);color:var(--ink)}
.fam b{font-size:15px;font-weight:600;direction:ltr;text-align:start;display:block;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fam span{font-family:var(--mono);font-size:12px;color:var(--ink-3);direction:ltr}
.fam__bar{grid-column:1/-1;height:6px;border-radius:999px;background:var(--sunk);overflow:hidden}
.fam__bar i{display:block;height:100%;border-radius:999px;background:var(--ink)}

.code{background:var(--ink);border-radius:22px;padding:22px 24px;direction:ltr;text-align:left;
  overflow-x:auto}
.code pre{margin:0;font-family:var(--mono);font-size:13.5px;line-height:1.65;color:#E8E6DF;
  white-space:pre}
.files{background:var(--card);border:1px solid var(--line);border-radius:24px;overflow:hidden;
  list-style:none;margin:0;padding:0}
.files a{display:grid;grid-template-columns:minmax(0,1fr) 90px 24px;align-items:center;gap:16px;
  padding:16px 22px;border-bottom:1px solid var(--sunk);direction:ltr;transition:background .15s ease}
.files li:last-child a{border-bottom:0}
.files a:hover{background:var(--paper);color:var(--ink)}
.files b{font-family:var(--mono);font-size:13.5px;font-weight:400;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.files span{font-family:var(--mono);font-size:12px;color:var(--ink-3);text-align:right}
.files svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8}
.perm{display:flex;gap:8px;flex-wrap:wrap;list-style:none;margin:0;padding:0}
.perm li{padding:8px 14px;border-radius:999px;background:var(--tint);color:var(--tint-ink);
  font-size:13px;font-weight:600}
.perm li.is-no{background:var(--sunk);color:var(--ink-2)}

/* The column that follows you down the page: what to download, and the line
   to run once you have. */
.mdl__side{position:sticky;top:92px;display:flex;flex-direction:column;gap:24px;min-width:0}
.grab{background:var(--card);border:1px solid var(--line);border-radius:28px;padding:24px;
  display:flex;flex-direction:column;gap:18px}
.grab h2{margin:0;font-size:12px;font-weight:700;color:var(--ink-3);letter-spacing:.04em}
.grab__list{display:flex;flex-direction:column;gap:6px;list-style:none;margin:0;padding:0}
.grab__list a{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px;border-radius:14px;border:1px solid var(--line);background:var(--card);
  transition:border-color .15s ease,background .15s ease,color .15s ease}
.grab__list a:hover{border-color:var(--ink);background:var(--ink);color:#fff}
.grab__list b{display:block;font-size:14px;font-weight:700;direction:ltr}
.grab__list i{display:block;font-style:normal;font-size:12px;opacity:.6}
.grab__list span{font-family:var(--mono);font-size:12px;opacity:.7;direction:ltr;flex:none}
.grab__go{display:flex;align-items:center;justify-content:center;gap:10px;min-height:52px;
  border-radius:999px;background:var(--ink);color:var(--paper);font-size:15px;font-weight:700;
  transition:background .2s ease}
.grab__go:hover{background:#2A2A27;color:var(--paper)}
.grab__go svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.8}
.grab__cmd{position:relative;background:var(--ink);border-radius:16px;padding:14px 16px;
  direction:ltr;text-align:left}
.grab__cmd pre{margin:0;font-family:var(--mono);font-size:12.5px;line-height:1.55;color:#E9F542;
  white-space:pre-wrap;word-break:break-all}
.grab__two{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.grab__two a{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;
  border-radius:999px;border:1px solid var(--line);background:var(--card);font-size:14px;
  font-weight:600;transition:border-color .15s ease}
.grab__two a:hover{border-color:var(--ink);color:var(--ink)}
.grab__two svg{width:16px;height:16px;fill:currentColor}
.grab__meta{display:flex;flex-direction:column;gap:10px;padding-top:14px;
  border-top:1px solid var(--sunk);list-style:none;margin:0}
.grab__meta li{display:flex;justify-content:space-between;gap:12px;font-size:13px}
.grab__meta span{color:var(--ink-3)}
.grab__meta b{font-weight:600;direction:ltr;text-align:left;overflow-wrap:anywhere}
.near__side{display:flex;flex-direction:column;gap:16px}
.near__side>h2{margin:0;font-size:12px;font-weight:700;color:var(--ink-3);letter-spacing:.04em}
.near__side a{display:flex;align-items:center;gap:14px;background:var(--card);
  border:1px solid var(--line);border-radius:20px;padding:16px;
  transition:transform .2s ease,border-color .2s ease}
.near__side a:hover{transform:translateY(-2px);border-color:var(--ink);color:var(--ink)}
.near__side .badge{width:44px;height:44px;border-radius:12px;font-size:18px}
.near__side b{display:block;font-size:15px;font-weight:700;direction:ltr;text-align:start;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.near__side i{display:block;font-style:normal;font-size:12px;color:var(--ink-3);margin-top:2px}

@media(max-width:900px){
  .mdl{grid-template-columns:1fr;gap:32px}
  .mdl__side{position:static}
  .mdl__tile{width:56px;height:56px;border-radius:16px;font-size:24px}
  .mdl__id{gap:14px}
}

.grab__cmd{padding-bottom:44px}
.copy{position:absolute;inset-inline-end:10px;bottom:10px;font:inherit;font-size:12px;
  font-weight:600;padding:6px 12px;border-radius:999px;border:1px solid rgba(255,255,255,.2);
  background:transparent;color:rgba(255,255,255,.75);cursor:pointer;
  transition:background .15s ease,color .15s ease}
.copy:hover{background:var(--lime);color:var(--ink);border-color:var(--lime)}
.grab__list a[data-pick]{border-color:var(--ink)}

/* The sign-in gate.
   A rating needs an account and there is no way round saying so. What there is
   a way round is saying it in a status line nobody reads: this is a dialog,
   it is what the send button opens, and it says what is kept before it asks. */
.gate{border:0;border-radius:26px;padding:clamp(24px,4vw,34px);max-width:400px;width:calc(100% - 32px);
  background:var(--card);color:var(--ink);box-shadow:0 40px 90px -30px rgba(19,19,17,.45);
  text-align:start;position:relative}
.gate::backdrop{background:rgba(19,19,17,.42);backdrop-filter:blur(3px)}
.gate h3{margin:0 0 10px;font-size:22px;font-weight:900;letter-spacing:-.02em}
.gate p{margin:0;font-size:14px;line-height:1.65;color:var(--ink-2)}
.gate .rate__btn{margin:22px 0 16px;display:flex;justify-content:center;min-height:44px}
.gate__note{font-size:12px;color:var(--ink-3)}
.gate__x{position:absolute;top:14px;inset-inline-end:14px;margin:0}
.gate__x button{width:34px;height:34px;border-radius:50%;border:1px solid var(--line);
  background:var(--card);color:var(--ink-2);font-size:14px;cursor:pointer;line-height:1}
.gate__x button:hover{background:var(--sunk);color:var(--ink)}

/* ── the review thread ─────────────────────────────────────────────────────
   The card at the top of the page answers "is this any good" in a number.
   This answers "why", which takes paragraphs, a name and a face, and belongs
   in the column where the rest of the reading happens. */
.talk{display:flex;flex-direction:column;gap:20px}
.talk__lede{margin:0;font-size:clamp(17px,1.4vw,19px);line-height:1.8;color:var(--ink-2);max-width:62ch}
.talk__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.talk__row{display:grid;grid-template-columns:44px minmax(0,1fr);gap:16px;padding:20px 0;
  border-top:1px solid var(--line)}
.talk__row:first-child{border-top:0;padding-top:4px}
.talk__av{width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--ui);font-weight:900;font-size:17px;color:var(--ink);flex:none}
.talk__body{min-width:0}
.talk__top{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:6px}
.talk__top b{font-size:16px;font-weight:700;letter-spacing:-.01em}
.talk__top time{font-size:12.5px;color:var(--ink-3)}
.talk__stars{color:#F2B41C;font-size:14px;letter-spacing:1px;line-height:1}
.talk__stars i{color:var(--line-3);font-style:normal}
.talk__body>p{margin:0;font-size:16.5px;line-height:1.75;color:var(--ink);
  max-width:62ch;overflow-wrap:break-word}
.talk__foot{display:flex;align-items:center;gap:18px;flex-wrap:wrap;padding-top:6px}
.talk__note{font-size:13px;color:var(--ink-3);max-width:46ch;line-height:1.6}

/* The two most recent lines, under the score, kept short on purpose. */
.rate__peek{margin-top:18px;padding-top:16px;border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:10px}
.rate__peek .rate__who{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.rate__peek .rate__who b{font-size:14px;font-weight:700}

.rate__peek .rate__list{max-height:none}
.rate__peek p{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rate__all{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;
  font-size:13.5px;font-weight:600;color:var(--ink-2)}
.rate__all:hover{color:var(--green-ink)}

/* ── the verified mark ─────────────────────────────────────────────────────
   Not a photograph. The service keeps a one-way hash of the Google account id
   and a first name and nothing else, which is the promise made further down
   the page, so the avatar is the initial and the badge is the claim that can
   actually be made: a real Google account, one per person per tool. */
.vis-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.av{position:relative;display:inline-grid;flex:none;width:30px;height:30px}
.av__i{width:100%;height:100%;border-radius:50%;display:grid;place-items:center;
  font-family:var(--ui);font-weight:900;font-size:13px;color:var(--ink)}
.av__g{position:absolute;bottom:-2px;inset-inline-end:-3px;width:15px;height:15px;
  border-radius:50%;background:#fff;display:grid;place-items:center;
  box-shadow:0 0 0 1.5px var(--card),0 1px 2px rgba(19,19,17,.2)}
.av__g svg{width:10px;height:10px;display:block}
.av--big{width:44px;height:44px}
.av--big .av__i{font-size:17px}
.av--big .av__g{width:19px;height:19px;bottom:-1px;inset-inline-end:-2px}
.av--big .av__g svg{width:12px;height:12px}
.talk__row .av{grid-column:1}

/* The list already draws its own rule and the peek wrapper draws one too, so
   inside the card they stacked into two lines with a gap between them. */
.rate__peek .rate__list{margin:0;padding:0;border-top:0}
.rate__peek .rate__list li{padding:10px 0;margin:0;border-bottom:0;border-top:1px solid var(--sunk)}
.rate__peek .rate__list li:first-child{border-top:0}

/* ── the article's opening ─────────────────────────────────────────────────
   The prose carries its own rhythm now, so this is the one typographic thing
   worth adding: an opening paragraph set larger, the way a magazine sets a
   standfirst. It costs no words and adds no heading, which the brief bans on
   purpose. */
.article>p:first-of-type{font-size:clamp(19px,1.7vw,22px);line-height:1.65;color:var(--ink);
  letter-spacing:-.005em}

/* ── the article's furniture ───────────────────────────────────────────────
   Everything here exists so the eye has somewhere to land between paragraphs.
   None of it is decoration bolted onto finished prose: the writer produces
   each one as a typed block, so a heading is four words because it was asked
   for as four words, and a facts card fits its grid because its value was
   capped at five. */
.art__h{margin:44px 0 16px;font-size:clamp(20px,2vw,24px);font-weight:900;letter-spacing:-.025em;
  color:var(--ink);display:flex;align-items:center;gap:12px;scroll-margin-top:92px}
.art__h::before{content:'';width:9px;height:9px;border-radius:50%;background:var(--green);flex:none}

.art__steps{margin:30px 0;display:flex;flex-direction:column;gap:14px}
.art__steps-t{margin:0;font-size:13px;font-weight:700;color:var(--ink-3);letter-spacing:.03em}
.art__steps ol{list-style:none;margin:0;padding:0;display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.art__steps li{background:var(--card);border:1px solid var(--line);border-radius:18px;
  padding:18px 20px;display:flex;align-items:flex-start;gap:12px;font-size:15.5px;
  font-weight:600;line-height:1.45;letter-spacing:-.01em;
  transition:border-color .2s ease,transform .2s ease}
.art__steps li:hover{border-color:var(--ink);transform:translateY(-2px)}
.art__steps li .mono{font-size:12px;font-weight:400;color:var(--green-ink);flex:none;padding-top:2px}

.art__facts{list-style:none;margin:28px 0;padding:0;display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.art__facts li{background:var(--card);border:1px solid var(--line);border-radius:18px;
  padding:16px 20px;display:flex;flex-direction:column;gap:6px}
.art__facts span{font-size:12.5px;color:var(--ink-3);font-weight:500}
.art__facts b{font-size:17px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
.art__facts b.is-good{color:var(--green-ink)}
.art__facts b.is-bad{color:#C0392B}

/* Their own sentence, in their own words, in a box that says so. */
.art__quote{margin:32px 0;background:var(--ink);color:#fff;border-radius:24px;
  padding:clamp(22px,3vw,30px);display:flex;flex-direction:column;gap:14px}
.art__quote p{margin:0;font-size:clamp(17px,1.5vw,19.5px);line-height:1.65;font-weight:600;
  color:#fff;max-width:none}
.art__quote cite{font-style:normal;font-size:12.5px;color:rgba(255,255,255,.55)}

.art__tip{margin:28px 0;background:var(--card);border:1px solid var(--line);
  border-radius:20px;padding:20px 24px;position:relative;overflow:hidden}
.art__tip::before{content:'';position:absolute;inset-block:0;inset-inline-start:0;width:4px;
  background:var(--green)}
.art__tip>b{display:block;font-size:12px;font-weight:700;color:var(--green-ink);
  letter-spacing:.04em;margin-bottom:6px}
.art__tip p{margin:0;font-size:15.5px;line-height:1.7;color:var(--ink-2);max-width:none}

/* The one line per article worth marking. */
.article mark{background:color-mix(in oklab,var(--green) 26%,transparent);color:inherit;
  padding:.08em .12em;border-radius:3px}

/* `.page__main .prose p` is (0,3,1) and wins over a single class, so every
   paragraph inside a block was being set at reading size: the steps label came
   out as body copy and the quote lost its weight. Scoped back here. */
.page__main .prose .art__steps-t{font-size:13px;font-weight:700;color:var(--ink-3);
  letter-spacing:.03em;margin:0 0 2px;max-width:none;line-height:1.4}
.page__main .prose .art__quote p{font-size:clamp(17px,1.5vw,19.5px);line-height:1.65;
  font-weight:600;color:#fff;margin:0;max-width:none}
.page__main .prose .art__tip p{font-size:15.5px;line-height:1.7;color:var(--ink-2);
  margin:0;max-width:none}
.page__main .prose .art__steps{margin:30px 0}
.page__main .prose .art__facts{margin:28px 0}

/* ── the FAQ, wherever it lands ────────────────────────────────────────────
   It was written for the tool page, where `.page__main` holds it to the
   measure. On the pages that place it straight under `<main>` — an
   organisation, the submit page — nothing held it at all: the heading ran off
   the right edge and the plus buttons sat against the left edge of the
   window. It carries its own wrap now, and gives it up again wherever a
   parent is already doing the job. */
.faq{max-width:var(--wrap);margin-inline:auto;padding-inline:clamp(16px,4vw,24px);
  box-sizing:border-box}
.page .faq,.band .faq,.page__main .faq,.tabs__panel .faq{max-width:none;padding-inline:0;margin-inline:0}

/* The line that joins a model to the company's own review, and back. */
.mdl__maker{margin:0;font-size:14px;color:rgba(255,255,255,.72);line-height:1.6}
.mdl__maker a{color:var(--lime);text-decoration:underline;text-underline-offset:3px}
.mdl__maker a:hover{color:#fff}


/* share ─────────────────────────────────────────────────────────────── */
.share{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:18px 0}
.share__l{font-size:12.5px;font-weight:700;letter-spacing:.04em;color:var(--ink-3)}
.share ul{list-style:none;margin:0;padding:0;display:flex;gap:6px;flex-wrap:wrap}
.share__b{position:relative;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:999px;
  border:1px solid var(--line);background:var(--card);color:var(--ink);cursor:pointer;padding:0;font:inherit;
  transition:transform .18s cubic-bezier(.2,.8,.2,1),border-color .18s,color .18s,background .18s}
.share__b svg{width:18px;height:18px;display:block}
.share__b:hover{transform:translateY(-2px);border-color:var(--ink);color:var(--green-ink)}
.share__b:focus-visible{outline:2px solid var(--green);outline-offset:2px}
.share__b--whatsapp:hover{color:#128C7E}
.share__b--facebook:hover{color:#1877F2}
.share__b--linkedin:hover{color:#0A66C2}
.share__b--telegram:hover{color:#229ED9}
.share__b.is-done{background:var(--tint);border-color:var(--tint-line);color:var(--tint-ink)}
.share__done{position:absolute;top:calc(100% + 6px);inset-inline-start:50%;transform:translateX(50%);white-space:nowrap;
  font-size:11.5px;font-weight:700;color:var(--tint-ink);pointer-events:none}
.share--compact{margin:10px 0}
.share--compact .share__b{width:34px;height:34px}
.share--compact .share__b svg{width:16px;height:16px}
@media (prefers-reduced-motion:reduce){.share__b{transition:none}.share__b:hover{transform:none}}

/* follow on Google ──────────────────────────────────────────────────── */
.follow-g{display:inline-flex;align-items:center;gap:14px;padding:12px 20px 12px 16px;border-radius:999px;
  border:1.5px solid var(--ink);background:var(--card);color:var(--ink);text-decoration:none;max-width:100%;
  transition:transform .18s cubic-bezier(.2,.8,.2,1),box-shadow .18s}
.follow-g:hover{color:var(--ink);transform:translateY(-2px);box-shadow:0 8px 24px -12px color-mix(in oklab,var(--ink) 40%,transparent)}
.follow-g__ic{flex:none;width:30px;height:30px;border-radius:999px;background:#fff;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line)}
.follow-g__ic svg{width:18px;height:18px;display:block}
.follow-g__t{display:flex;flex-direction:column;gap:2px;min-width:0}
.follow-g__t b{font-size:15.5px;font-weight:800;letter-spacing:-.01em;line-height:1.2}
.follow-g__t span{font-size:12.5px;color:var(--ink-2);line-height:1.4}
.follow-g--compact{padding:8px 14px 8px 10px;gap:10px;border-width:1px}
.follow-g--compact .follow-g__ic{width:24px;height:24px}
.follow-g--compact .follow-g__ic svg{width:14px;height:14px}
.follow-g--compact .follow-g__t b{font-size:13.5px}
.follow-g--dark{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.follow-g--dark:hover{color:var(--paper)}
.follow-g--dark .follow-g__t span{color:color-mix(in oklab,var(--paper) 65%,transparent)}

/* the guides page ─────────────────────────────────────────────────── */
.guide-list{list-style:none;margin:0 0 24px;padding:0;display:grid;gap:10px}
.guide-list a{display:grid;gap:4px;padding:16px 18px;border:1px solid var(--line);border-radius:14px;background:var(--card);color:var(--ink);text-decoration:none;transition:border-color .15s}
.guide-list a:hover{border-color:var(--ink)}
.guide-list b{font-family:var(--disp);font-weight:700;font-size:24px;line-height:1.1}
.guide-list span{font-size:14.5px;color:var(--ink-2);line-height:1.5}
